ncurses/ncurses-5.5-pthread.dif

206 lines
5.2 KiB
Plaintext

--- 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 <pthread.h>
+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 <ncurses_dll.h>
+#if defined _REENTRANT || defined _THREAD_SAFE
+# include <pthread.h>
+#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 <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 @@
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