Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifdef HAVE_CONFIG_H
00024 #include <config.h>
00025 #endif
00026
00027 #include <signal.h>
00028 #include <string.h>
00029
00030 #include "quit.h"
00031
00032 octave_jmp_buf current_context;
00033
00034 void
00035 octave_save_current_context (void *save_buf)
00036 {
00037 memcpy (save_buf, current_context, sizeof (octave_jmp_buf));
00038 }
00039
00040 void
00041 octave_restore_current_context (void *save_buf)
00042 {
00043 memcpy (current_context, save_buf, sizeof (octave_jmp_buf));
00044 }
00045
00046 #if defined (__WIN32__) && ! defined (_POSIX_VERSION)
00047
00048
00049 #if defined (DEBUG)
00050
00051 #define PRINT_CURRENT_THREAD() printf ("%lx: ", GetCurrentThreadId ())
00052
00053 #define DEBUGs(s) \
00054 do \
00055 { \
00056 PRINT_CURRENT_THREAD (); \
00057 printf (s "\n"); \
00058 fflush (stdout); \
00059 } \
00060 while (0)
00061
00062 #define DEBUGd(s, d) \
00063 do \
00064 { \
00065 PRINT_CURRENT_THREAD (); \
00066 printf (s "\n", d); \
00067 fflush (stdout); \
00068 } \
00069 while (0)
00070
00071 #else
00072 #define DEBUGs(s)
00073 #define DEBUGd(s, d)
00074 #endif
00075
00076 CRITICAL_SECTION w32_thread_setjmp_mutex;
00077 static CONTEXT w32_signal_context;
00078 static int w32_signal_to_raise = 0;
00079 static DWORD w32_main_thread_id;
00080 static HANDLE w32_main_thread;
00081 static HANDLE w32_restore_thread = NULL;
00082
00083 int
00084 w32_in_main_thread(void)
00085 {
00086 return (GetCurrentThreadId () == w32_main_thread_id);
00087 }
00088
00089 static DWORD WINAPI
00090 w32_reset_context (LPVOID v)
00091 {
00092 PCONTEXT context = (PCONTEXT)v;
00093 int ret;
00094
00095
00096 EnterCriticalSection (&w32_thread_setjmp_mutex);
00097
00098 DEBUGs ("enter w32_set_context");
00099 SuspendThread (w32_main_thread);
00100 DEBUGs ("main suspended");
00101 if (! SetThreadContext (w32_main_thread, context))
00102 {
00103 fprintf (stderr, "%lx: context failed: ctrl-c won't work\n",
00104 GetCurrentThreadId ());
00105 fflush (stderr);
00106 }
00107 DEBUGs ("context captured (or not)");
00108 ret = ResumeThread (w32_main_thread);
00109 DEBUGd ("main resumed with %d", ret);
00110
00111 LeaveCriticalSection (&w32_thread_setjmp_mutex);
00112 return 0;
00113 }
00114
00115 static void
00116 w32_raise_in_main (void)
00117 {
00118 DWORD threadid;
00119
00120 DEBUGd ("w32_raise_in_main with signal %d", w32_signal_to_raise);
00121 raise (w32_signal_to_raise);
00122 DEBUGd ("w32_raise_in_main signal %d returned a value",
00123 w32_signal_to_raise);
00124
00125 DEBUGs ("attempting to restore main to pre-signal configuration");
00126 if (w32_restore_thread != NULL)
00127 CloseHandle (w32_restore_thread);
00128 w32_restore_thread = CreateThread (NULL, 10000, w32_reset_context,
00129 &w32_signal_context, 0, &threadid);
00130 if (w32_restore_thread == NULL)
00131 {
00132 fprintf (stderr, "w32_raise_in_main couldn't create thread\n");
00133 fflush (stderr);
00134 }
00135 else
00136 {
00137 DEBUGs ("waiting to restore raise context");
00138 WaitForSingleObject (w32_restore_thread, INFINITE);
00139 fprintf (stderr, "w32_raise_in_main couldn't restore context\n");
00140 fflush (stderr);
00141 }
00142 }
00143
00144 void
00145 w32_raise_final (void)
00146 {
00147 CloseHandle (w32_main_thread);
00148 if (w32_restore_thread != NULL)
00149 CloseHandle (w32_restore_thread);
00150 w32_main_thread = w32_restore_thread = NULL;
00151 }
00152
00153
00154
00155 void
00156 w32_raise (int sig)
00157 {
00158 int ret;
00159
00160 if (w32_in_main_thread ())
00161 {
00162
00163 DEBUGd ("raising signal %d within main", signal);
00164 raise (sig);
00165 DEBUGd ("returning from signal %d within main", signal);
00166 }
00167 else
00168 {
00169
00170
00171 CONTEXT raise_context;
00172 DEBUGd ("raising signal %d from separate thread", signal);
00173
00174
00175 SuspendThread (w32_main_thread);
00176
00177 w32_signal_context.ContextFlags
00178 = CONTEXT_FULL|CONTEXT_FLOATING_POINT|CONTEXT_DEBUG_REGISTERS;
00179 GetThreadContext (w32_main_thread, &w32_signal_context);
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190 memcpy (&raise_context, &w32_signal_context, sizeof (CONTEXT));
00191 raise_context.Eip = (DWORD)&w32_raise_in_main;
00192 w32_signal_to_raise = sig;
00193 SetThreadContext (w32_main_thread, &raise_context);
00194
00195
00196 ret = ResumeThread (w32_main_thread);
00197 DEBUGd ("main resumed at w32_raise_in_main with suspend count %d",
00198 ret);
00199 }
00200 }
00201
00202 void
00203 w32_sigint_init (void)
00204 {
00205
00206 w32_main_thread_id = GetCurrentThreadId ();
00207 DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
00208 GetCurrentProcess (), &w32_main_thread,
00209 0, FALSE, DUPLICATE_SAME_ACCESS);
00210
00211 InitializeCriticalSectionAndSpinCount (&w32_thread_setjmp_mutex, 0);
00212 }
00213
00214 #endif
00215
00216 void
00217 octave_jump_to_enclosing_context (void)
00218 {
00219 #if defined (OCTAVE_HAVE_SIG_JUMP)
00220 siglongjmp (current_context, 1);
00221 #else
00222 longjmp (current_context, 1);
00223 #endif
00224 }
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234 static sigset_t octave_signal_mask;
00235
00236 void
00237 octave_save_signal_mask (void)
00238 {
00239 sigprocmask (0, 0, &octave_signal_mask);
00240 }
00241
00242 void
00243 octave_restore_signal_mask (void)
00244 {
00245 sigprocmask (SIG_SETMASK, &octave_signal_mask, 0);
00246 }
00247
00248 sig_atomic_t octave_interrupt_immediately = 0;
00249
00250 sig_atomic_t octave_interrupt_state = 0;
00251
00252 sig_atomic_t octave_exception_state = 0;
00253
00254 volatile sig_atomic_t octave_signal_caught = 0;