forked from pool/ncurses
238 lines
6.3 KiB
Plaintext
238 lines
6.3 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
|
|
@@ -594,6 +598,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 */
|
|
@@ -1214,6 +1223,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 (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 2007-01-31 13:08:37.000000000 +0100
|
|
@@ -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
|