SHA256
1
0
forked from pool/ncurses
ncurses/ncurses-5.6-pthread.dif

247 lines
6.5 KiB
Plaintext

--- ncurses/SigAction.h
+++ ncurses/SigAction.h 2007-01-31 12:39:37.000000000 +0100
@@ -55,6 +55,53 @@
typedef struct sigaction sigaction_t;
#endif
+#if defined(__GNUC__) && defined(linux)
+# if defined __USE_ISOC99
+# define _cat_pragma(exp) _Pragma(#exp)
+# define _weak_pragma(exp) _cat_pragma(weak name)
+# else
+# define _weak_pragma(exp)
+# endif
+# define _declare(name) __extension__ extern __typeof__(name) name
+# define weak_symbol(name) _weak_pragma(name) _declare(name) __attribute__((weak))
+#else
+# if defined(linux) && (defined(_REENTRANT) || defined(_THREAD_SAFE))
+# error The ncurses library has to be NPTL thread safe (requires the GCC)
+# endif
+#endif
+
+#if defined(linux) && (defined(_REENTRANT) || defined(_THREAD_SAFE))
+# include <pthread.h>
+
+weak_symbol(pthread_sigmask);
+weak_symbol(pthread_kill);
+weak_symbol(pthread_self);
+weak_symbol(pthread_equal);
+
+static inline int _nc__sigprocmask(int how, const sigset_t *newmask, sigset_t *oldmask)
+{
+ if ((pthread_sigmask))
+ return pthread_sigmask(how, newmask, oldmask);
+ else
+ return sigprocmask(how, newmask, oldmask);
+}
+# undef sigprocmask
+# define sigprocmask _nc__sigprocmask
+
+static inline void _nc_kill(SCREEN *scan, int signal)
+{
+ if (!scan || !scan->_read_thread)
+ goto out;
+ if (!(pthread_kill) || !(pthread_equal) || !(pthread_self))
+ goto out;
+ if (pthread_equal(scan->_read_thread, pthread_self()))
+ goto out;
+ pthread_kill(scan->_read_thread, signal);
+out:
+ return;
+}
+#endif
+
#else /* !HAVE_SIGACTION */
#if HAVE_SIGVEC
--- ncurses/curses.priv.h
+++ ncurses/curses.priv.h 2007-01-31 12:40:37.000000000 +0100
@@ -48,6 +48,10 @@
#include <ncurses_dll.h>
+#if defined(linux) && (defined(_REENTRANT) || defined(_THREAD_SAFE))
+# include <pthread.h>
+#endif
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -591,6 +595,11 @@ struct screen {
#define _nc_windows SP->_nc_sp_windows
bool _sig_winch;
+#if USE_SIGWINCH
+# if defined(linux) && (defined(_REENTRANT) || defined(_THREAD_SAFE))
+ pthread_t _read_thread;
+# endif
+#endif
SCREEN *_next_screen;
/* hashes for old and new lines */
@@ -1209,6 +1218,9 @@ extern NCURSES_EXPORT(void) _nc_scroll_o
extern NCURSES_EXPORT(void) _nc_scroll_optimize (void);
extern NCURSES_EXPORT(void) _nc_set_buffer (FILE *, bool);
extern NCURSES_EXPORT(void) _nc_signal_handler (bool);
+#if USE_SIGWINCH
+extern NCURSES_EXPORT(void) _nc_thread(SCREEN *);
+#endif
extern NCURSES_EXPORT(void) _nc_synchook (WINDOW *);
extern NCURSES_EXPORT(void) _nc_trace_tries (struct tries *);
--- ncurses/base/lib_getch.c
+++ ncurses/base/lib_getch.c 2007-01-31 12:41:27.000000000 +0100
@@ -237,6 +237,10 @@ _nc_wgetch(WINDOW *win,
if (win == 0 || SP == 0)
returnCode(ERR);
+#if USE_SIGWINCH
+ _nc_thread(SP);
+#endif
+
if (cooked_key_in_fifo()) {
if (wgetch_should_refresh(win))
wrefresh(win);
--- ncurses/base/lib_set_term.c
+++ ncurses/base/lib_set_term.c 2008-04-08 15:18:15.230819462 +0200
@@ -40,7 +40,7 @@
*/
#include <curses.priv.h>
-
+#include <SigAction.h>
#include <term.h> /* cur_term */
#include <tic.h>
@@ -144,6 +144,12 @@ delscreen(SCREEN *sp)
free(sp->_setbuf);
}
+#if USE_SIGWINCH
+# if defined(linux) && (defined(_REENTRANT) || defined(_THREAD_SAFE))
+ sp->_read_thread = (pthread_t)0;
+# endif
+#endif
+
free(sp);
/*
@@ -559,6 +565,15 @@ _nc_setupscreen(int slines,
returnCode(ERR);
SP->_stdscr = stdscr;
+#if USE_SIGWINCH
+# if defined(linux) && (defined(_REENTRANT) || defined(_THREAD_SAFE))
+ if ((pthread_self))
+ SP->_read_thread = pthread_self();
+ else
+ SP->_read_thread = (pthread_t)0;
+# endif
+#endif
+
returnCode(OK);
}
--- ncurses/tinfo/lib_setup.c
+++ ncurses/tinfo/lib_setup.c 2007-01-31 11:46:17.000000000 +0100
@@ -42,6 +42,7 @@
#include <curses.priv.h>
#include <tic.h> /* for MAX_NAME_SIZE */
#include <term_entry.h>
+#include <SigAction.h>
#if SVR4_TERMIO && !defined(_POSIX_SOURCE)
#define _POSIX_SOURCE
@@ -119,6 +120,13 @@ _nc_handle_sigwinch(int enable)
default:
/* record a SIGWINCH */
have_sigwinch = 1;
+# if defined(linux) && (defined(_REENTRANT) || defined(_THREAD_SAFE))
+ scan = _nc_screen_chain;
+ while (scan) {
+ _nc_kill(scan, SIGWINCH);
+ scan = scan->_next_screen;
+ }
+# endif
break;
case 0:
/* temporarily disable the next block */
--- ncurses/tty/lib_tstp.c
+++ ncurses/tty/lib_tstp.c 2007-01-31 13:14:40.000000000 +0100
@@ -142,6 +142,11 @@ tstp(int dummy GCC_UNUSED)
#ifdef SIGTTOU
int sigttou_blocked;
#endif
+#if USE_SIGWINCH
+# if defined(linux) && (defined(_REENTRANT) || defined(_THREAD_SAFE))
+ pthread_t reader = (pthread_t)0;
+# endif
+#endif
T(("tstp() called"));
@@ -169,6 +174,10 @@ tstp(int dummy GCC_UNUSED)
(void) sigaddset(&mask, SIGALRM);
#if USE_SIGWINCH
(void) sigaddset(&mask, SIGWINCH);
+# if defined(linux) && (defined(_REENTRANT) || defined(_THREAD_SAFE))
+ reader = SP->_read_thread;
+ SP->_read_thread = (pthread_t)0;
+# endif
#endif
(void) sigprocmask(SIG_BLOCK, &mask, &omask);
@@ -214,6 +223,12 @@ tstp(int dummy GCC_UNUSED)
sigaction(SIGTSTP, &oact, NULL);
flushinp();
+#if USE_SIGWINCH
+# if defined(linux) && (defined(_REENTRANT) || defined(_THREAD_SAFE))
+ SP->_read_thread = reader;
+# endif
+#endif
+
/*
* If the user modified the tty state while suspended, he wants
* those changes to stick. So save the new "default" terminal state.
@@ -386,6 +401,13 @@ _nc_signal_handler(bool enable)
CatchIfDefault(SIGINT, cleanup);
CatchIfDefault(SIGTERM, cleanup);
#if USE_SIGWINCH
+# if defined(linux) && (defined(_REENTRANT) || defined(_THREAD_SAFE))
+ if ((pthread_self) && (pthread_equal)) {
+ pthread_t current = pthread_self();
+ if (!pthread_equal(SP->_read_thread, current))
+ SP->_read_thread = current;
+ }
+# endif
CatchIfDefault(SIGWINCH, sigwinch);
#endif
initialized = TRUE;
@@ -393,3 +415,25 @@ _nc_signal_handler(bool enable)
}
returnVoid;
}
+
+#if USE_SIGWINCH
+/*
+ * This is invoked once at the beginning of reading, to remember
+ * which thread should be interrupted if the SIGWINCH handler is
+ * called.
+ */
+
+NCURSES_EXPORT(void)
+_nc_thread(SCREEN *scan)
+{
+# if defined(linux) && (defined(_REENTRANT) || defined(_THREAD_SAFE))
+ if ((pthread_self) && (pthread_equal)) {
+ pthread_t current = pthread_self();
+ if (pthread_equal(SP->_read_thread, current))
+ return;
+ /* Remember the terminal reading thread */
+ scan->_read_thread = current;
+ }
+# endif
+}
+#endif