--- ncurses/SigAction.h +++ ncurses/SigAction.h 2006-05-18 14:31:29.000000000 +0200 @@ -55,6 +55,36 @@ typedef struct sigaction sigaction_t; #endif +#if defined _REENTRANT || defined _THREAD_SAFE +# include +extern int pthread_sigmask(int, const sigset_t*, sigset_t*) __attribute__((weak)); +extern int pthread_kill(pthread_t, int) __attribute__((weak)); +extern pthread_t pthread_self(void) __attribute__((weak)); +extern int pthread_equal(pthread_t, pthread_t) __attribute__((weak)); + +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); +} +#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 2006-05-18 14:31:29.000000000 +0200 @@ -48,6 +48,10 @@ #include +#if defined _REENTRANT || defined _THREAD_SAFE +# include +#endif + #ifdef __cplusplus extern "C" { #endif @@ -538,6 +542,12 @@ #define _nc_windows SP->_nc_sp_windows bool _sig_winch; +#if USE_SIGWINCH + bool _unblock_sigwinch; +#if defined _REENTRANT || defined _THREAD_SAFE + pthread_t _read_thread; +#endif +#endif SCREEN *_next_screen; /* hashes for old and new lines */ @@ -1143,6 +1153,9 @@ 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_unblock (SCREEN *, int); +#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 2006-05-18 14:31:29.000000000 +0200 @@ -237,6 +237,10 @@ if (win == 0 || SP == 0) returnCode(ERR); +#if USE_SIGWINCH + _nc_unblock(SP, SIGWINCH); +#endif + if (cooked_key_in_fifo()) { if (wgetch_should_refresh(win)) wrefresh(win); --- ncurses/tinfo/lib_setup.c +++ ncurses/tinfo/lib_setup.c 2006-05-18 15:24:54.000000000 +0200 @@ -42,6 +42,7 @@ #include #include /* for MAX_NAME_SIZE */ #include +#include #if SVR4_TERMIO && !defined(_POSIX_SOURCE) #define _POSIX_SOURCE @@ -119,6 +120,13 @@ default: /* record a SIGWINCH */ have_sigwinch = 1; +# if 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 2006-05-18 15:53:04.000000000 +0200 @@ -142,6 +142,9 @@ #ifdef SIGTTOU int sigttou_blocked; #endif +#if defined _REENTRANT || defined _THREAD_SAFE + pthread_t reader = (pthread_t)0; +#endif T(("tstp() called")); @@ -169,6 +172,10 @@ (void) sigaddset(&mask, SIGALRM); #if USE_SIGWINCH (void) sigaddset(&mask, SIGWINCH); +#if 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 +221,10 @@ sigaction(SIGTSTP, &oact, NULL); flushinp(); +#if defined _REENTRANT || defined _THREAD_SAFE + SP->_read_thread = reader; +#endif + /* * If the user modified the tty state while suspended, he wants * those changes to stick. So save the new "default" terminal state. @@ -332,6 +343,17 @@ result = FALSE; } #endif + +#if USE_SIGWINCH + if (result && sig == SIGWINCH) { + sigset_t sigset; + + sigemptyset(&sigset); + sigaddset(&sigset, SIGWINCH); + sigprocmask(SIG_BLOCK, &sigset, NULL); + } +#endif + T(("CatchIfDefault - will %scatch %s", result ? "" : "not ", signal_name(sig))); return result; @@ -386,6 +408,10 @@ CatchIfDefault(SIGINT, cleanup); CatchIfDefault(SIGTERM, cleanup); #if USE_SIGWINCH + SP->_unblock_sigwinch = false; +# if defined _REENTRANT || defined _THREAD_SAFE + SP->_read_thread = (pthread_t)0; +# endif CatchIfDefault(SIGWINCH, sigwinch); #endif initialized = TRUE; @@ -393,3 +419,29 @@ } 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_unblock(SCREEN *scan, int signal) +{ + sigset_t sigset; + + if (scan->_unblock_sigwinch) + return; + sigemptyset(&sigset); + sigaddset(&sigset, signal); + sigprocmask(SIG_UNBLOCK, &sigset, NULL); +# if defined _REENTRANT || defined _THREAD_SAFE + /* Remember the terminal reading thread */ + if (&pthread_self) + scan->_read_thread = pthread_self(); +# endif + scan->_unblock_sigwinch = true; +} +#endif