Mercurial > octave-nkf
annotate libcruft/misc/cquit.c @ 8838:dea5bd01e6d7
omission from last patch
author | Jaroslav Hajek <highegg@gmail.com> |
---|---|
date | Mon, 23 Feb 2009 12:47:30 +0100 |
parents | 78f3811155f7 |
children | eb63fbe60fab |
rev | line source |
---|---|
4571 | 1 /* |
2 | |
7017 | 3 Copyright (C) 2003, 2005, 2006, 2007 John W. Eaton |
4571 | 4 |
5 This file is part of Octave. | |
6 | |
7 Octave is free software; you can redistribute it and/or modify it | |
8 under the terms of the GNU General Public License as published by the | |
7016 | 9 Free Software Foundation; either version 3 of the License, or (at your |
10 option) any later version. | |
4571 | 11 |
12 Octave is distributed in the hope that it will be useful, but WITHOUT | |
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
15 for more details. | |
16 | |
17 You should have received a copy of the GNU General Public License | |
7016 | 18 along with Octave; see the file COPYING. If not, see |
19 <http://www.gnu.org/licenses/>. | |
4571 | 20 |
21 */ | |
22 | |
23 #ifdef HAVE_CONFIG_H | |
24 #include <config.h> | |
25 #endif | |
26 | |
27 #include <signal.h> | |
28 #include <string.h> | |
29 | |
30 #include "quit.h" | |
31 | |
32 octave_jmp_buf current_context; | |
33 | |
34 void | |
35 octave_save_current_context (void *save_buf) | |
36 { | |
37 memcpy (save_buf, current_context, sizeof (octave_jmp_buf)); | |
38 } | |
39 | |
40 void | |
41 octave_restore_current_context (void *save_buf) | |
42 { | |
43 memcpy (current_context, save_buf, sizeof (octave_jmp_buf)); | |
44 } | |
45 | |
5451 | 46 #if defined (__WIN32__) && ! defined (_POSIX_VERSION) |
47 | |
5775 | 48 /* FIXME -- eventually remove the debugging */ |
5451 | 49 #if defined (DEBUG) |
50 | |
51 #define PRINT_CURRENT_THREAD() printf ("%lx: ", GetCurrentThreadId ()) | |
52 | |
53 #define DEBUGs(s) \ | |
54 do \ | |
55 { \ | |
56 PRINT_CURRENT_THREAD (); \ | |
57 printf (s "\n"); \ | |
58 fflush (stdout); \ | |
59 } \ | |
60 while (0) | |
61 | |
62 #define DEBUGd(s, d) \ | |
63 do \ | |
64 { \ | |
65 PRINT_CURRENT_THREAD (); \ | |
66 printf (s "\n", d); \ | |
67 fflush (stdout); \ | |
68 } \ | |
69 while (0) | |
70 | |
71 #else | |
72 #define DEBUGs(s) | |
73 #define DEBUGd(s, d) | |
74 #endif | |
75 | |
76 CRITICAL_SECTION w32_thread_setjmp_mutex; | |
77 static CONTEXT w32_signal_context; | |
78 static int w32_signal_to_raise = 0; | |
79 static DWORD w32_main_thread_id; | |
80 static HANDLE w32_main_thread; | |
81 static HANDLE w32_restore_thread = NULL; | |
82 | |
83 int | |
84 w32_in_main_thread(void) | |
85 { | |
86 return (GetCurrentThreadId () == w32_main_thread_id); | |
87 } | |
88 | |
89 static DWORD WINAPI | |
90 w32_reset_context (LPVOID v) | |
91 { | |
92 PCONTEXT context = (PCONTEXT)v; | |
93 int ret; | |
94 | |
95 /* Mutex the setjmp/longjmp */ | |
96 EnterCriticalSection (&w32_thread_setjmp_mutex); | |
97 | |
98 DEBUGs ("enter w32_set_context"); | |
99 SuspendThread (w32_main_thread); | |
100 DEBUGs ("main suspended"); | |
101 if (! SetThreadContext (w32_main_thread, context)) | |
102 { | |
103 fprintf (stderr, "%lx: context failed: ctrl-c won't work\n", | |
104 GetCurrentThreadId ()); | |
105 fflush (stderr); | |
106 } | |
107 DEBUGs ("context captured (or not)"); | |
108 ret = ResumeThread (w32_main_thread); | |
109 DEBUGd ("main resumed with %d", ret); | |
110 | |
111 LeaveCriticalSection (&w32_thread_setjmp_mutex); | |
112 return 0; | |
113 } | |
114 | |
115 static void | |
116 w32_raise_in_main (void) | |
117 { | |
118 DWORD threadid; | |
119 | |
120 DEBUGd ("w32_raise_in_main with signal %d", w32_signal_to_raise); | |
121 raise (w32_signal_to_raise); | |
122 DEBUGd ("w32_raise_in_main signal %d returned a value", | |
123 w32_signal_to_raise); | |
124 | |
125 DEBUGs ("attempting to restore main to pre-signal configuration"); | |
126 if (w32_restore_thread != NULL) /* Catch leaky threads */ | |
127 CloseHandle (w32_restore_thread); | |
128 w32_restore_thread = CreateThread (NULL, 10000, w32_reset_context, | |
129 &w32_signal_context, 0, &threadid); | |
130 if (w32_restore_thread == NULL) | |
131 { | |
132 fprintf (stderr, "w32_raise_in_main couldn't create thread\n"); | |
133 fflush (stderr); | |
134 } | |
135 else | |
136 { | |
137 DEBUGs ("waiting to restore raise context"); | |
138 WaitForSingleObject (w32_restore_thread, INFINITE); | |
139 fprintf (stderr, "w32_raise_in_main couldn't restore context\n"); | |
140 fflush (stderr); | |
141 } | |
142 } | |
143 | |
144 void | |
145 w32_raise_final (void) | |
146 { | |
147 CloseHandle (w32_main_thread); | |
148 if (w32_restore_thread != NULL) /* Catch leaky threads */ | |
149 CloseHandle (w32_restore_thread); | |
150 w32_main_thread = w32_restore_thread = NULL; | |
151 } | |
152 | |
153 /* Raise the given signal in the main thread. w32_raise_init () | |
154 must have been called from the main thread already. */ | |
155 void | |
156 w32_raise (int sig) | |
157 { | |
158 int ret; | |
159 | |
160 if (w32_in_main_thread ()) | |
161 { | |
162 /* Called from main thread -- a simple raise () should work. */ | |
163 DEBUGd ("raising signal %d within main", signal); | |
164 raise (sig); | |
165 DEBUGd ("returning from signal %d within main", signal); | |
166 } | |
167 else | |
168 { | |
169 /* Called from alternate thread -- call w32_raise_in_main in the | |
170 main thread with w32_signal_to_raise set to the signal */ | |
171 CONTEXT raise_context; | |
172 DEBUGd ("raising signal %d from separate thread", signal); | |
173 | |
174 /* Suspend main and remember the context. */ | |
175 SuspendThread (w32_main_thread); | |
176 /* X86 code */ | |
177 w32_signal_context.ContextFlags | |
178 = CONTEXT_FULL|CONTEXT_FLOATING_POINT|CONTEXT_DEBUG_REGISTERS; | |
179 GetThreadContext (w32_main_thread, &w32_signal_context); | |
180 | |
181 /* Change the context to w32_raise_in_main. The | |
182 context.Eip=&fn trick for setting the program counter is | |
183 courtesy of | |
184 | |
185 http://fit.c2.com/files/LispPlatform/lisp/clisp-2.28/src/win32aux.d | |
186 | |
187 Auxiliary functions for CLISP on Win32, Bruno Haible | |
188 1997-1999. */ | |
189 | |
190 memcpy (&raise_context, &w32_signal_context, sizeof (CONTEXT)); | |
191 raise_context.Eip = (DWORD)&w32_raise_in_main; /* X86 code */ | |
192 w32_signal_to_raise = sig; | |
193 SetThreadContext (w32_main_thread, &raise_context); | |
194 | |
195 /* Resume main at w32_raise_in_main */ | |
196 ret = ResumeThread (w32_main_thread); | |
197 DEBUGd ("main resumed at w32_raise_in_main with suspend count %d", | |
198 ret); | |
199 } | |
200 } | |
201 | |
202 void | |
203 w32_sigint_init (void) | |
204 { | |
205 /* Capture main context */ | |
206 w32_main_thread_id = GetCurrentThreadId (); | |
207 DuplicateHandle (GetCurrentProcess (), GetCurrentThread (), | |
208 GetCurrentProcess (), &w32_main_thread, | |
209 0, FALSE, DUPLICATE_SAME_ACCESS); | |
210 | |
211 InitializeCriticalSectionAndSpinCount (&w32_thread_setjmp_mutex, 0); | |
212 } | |
213 | |
214 #endif /* #if defined (__WIN32__) && ! defined (_POSIX_VERSION) */ | |
215 | |
4571 | 216 void |
217 octave_jump_to_enclosing_context (void) | |
218 { | |
219 #if defined (OCTAVE_HAVE_SIG_JUMP) | |
220 siglongjmp (current_context, 1); | |
221 #else | |
222 longjmp (current_context, 1); | |
223 #endif | |
224 } | |
225 | |
4572 | 226 /* Allow us to save the signal mask and then restore it to the most |
227 recently saved value. This is necessary when using the POSIX | |
228 signal handling interface on some systems calling longjmp out of | |
229 the signal handler to get to the top level on an interrupt doesn't | |
230 restore the original signal mask. Alternatively, we could use | |
231 sigsetjmp/siglongjmp, but saving and restoring the signal mask | |
232 ourselves works ok and seems simpler just now. */ | |
4571 | 233 |
234 #if defined (HAVE_POSIX_SIGNALS) | |
235 static sigset_t octave_signal_mask; | |
236 #endif | |
237 | |
238 void | |
239 octave_save_signal_mask (void) | |
240 { | |
241 #if defined (HAVE_POSIX_SIGNALS) | |
242 sigprocmask (0, 0, &octave_signal_mask); | |
243 #endif | |
244 } | |
245 | |
246 void | |
247 octave_restore_signal_mask (void) | |
248 { | |
249 #if defined (HAVE_POSIX_SIGNALS) | |
250 sigprocmask (SIG_SETMASK, &octave_signal_mask, 0); | |
251 #endif | |
252 } | |
253 | |
254 sig_atomic_t octave_interrupt_immediately = 0; | |
255 | |
256 sig_atomic_t octave_interrupt_state = 0; | |
257 | |
7481
78f3811155f7
use exceptions in liboctave error handler
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
258 sig_atomic_t octave_exception_state = 0; |
4571 | 259 |
8838
dea5bd01e6d7
omission from last patch
Jaroslav Hajek <highegg@gmail.com>
parents:
7481
diff
changeset
|
260 volatile sig_atomic_t octave_signal_caught = 0; |
5142 | 261 |
4571 | 262 /* |
263 ;;; Local Variables: *** | |
264 ;;; mode: C++ *** | |
265 ;;; End: *** | |
266 */ |