comparison libcruft/misc/cquit.c @ 5451:ed08548b9054

[project @ 2005-09-15 19:52:50 by jwe]
author jwe
date Thu, 15 Sep 2005 19:52:50 +0000
parents 4c8a2e4e0717
children ace8d8d26933
comparison
equal deleted inserted replaced
5450:6b42c78c77d3 5451:ed08548b9054
41 void 41 void
42 octave_restore_current_context (void *save_buf) 42 octave_restore_current_context (void *save_buf)
43 { 43 {
44 memcpy (current_context, save_buf, sizeof (octave_jmp_buf)); 44 memcpy (current_context, save_buf, sizeof (octave_jmp_buf));
45 } 45 }
46
47 #if defined (__WIN32__) && ! defined (_POSIX_VERSION)
48
49 /* XXX FIXME XXX -- eventually remove the debugging */
50 #if defined (DEBUG)
51
52 #define PRINT_CURRENT_THREAD() printf ("%lx: ", GetCurrentThreadId ())
53
54 #define DEBUGs(s) \
55 do \
56 { \
57 PRINT_CURRENT_THREAD (); \
58 printf (s "\n"); \
59 fflush (stdout); \
60 } \
61 while (0)
62
63 #define DEBUGd(s, d) \
64 do \
65 { \
66 PRINT_CURRENT_THREAD (); \
67 printf (s "\n", d); \
68 fflush (stdout); \
69 } \
70 while (0)
71
72 #else
73 #define DEBUGs(s)
74 #define DEBUGd(s, d)
75 #endif
76
77 CRITICAL_SECTION w32_thread_setjmp_mutex;
78 static CONTEXT w32_signal_context;
79 static int w32_signal_to_raise = 0;
80 static DWORD w32_main_thread_id;
81 static HANDLE w32_main_thread;
82 static HANDLE w32_restore_thread = NULL;
83
84 int
85 w32_in_main_thread(void)
86 {
87 return (GetCurrentThreadId () == w32_main_thread_id);
88 }
89
90 static DWORD WINAPI
91 w32_reset_context (LPVOID v)
92 {
93 PCONTEXT context = (PCONTEXT)v;
94 int ret;
95
96 /* Mutex the setjmp/longjmp */
97 EnterCriticalSection (&w32_thread_setjmp_mutex);
98
99 DEBUGs ("enter w32_set_context");
100 SuspendThread (w32_main_thread);
101 DEBUGs ("main suspended");
102 if (! SetThreadContext (w32_main_thread, context))
103 {
104 fprintf (stderr, "%lx: context failed: ctrl-c won't work\n",
105 GetCurrentThreadId ());
106 fflush (stderr);
107 }
108 DEBUGs ("context captured (or not)");
109 ret = ResumeThread (w32_main_thread);
110 DEBUGd ("main resumed with %d", ret);
111
112 LeaveCriticalSection (&w32_thread_setjmp_mutex);
113 return 0;
114 }
115
116 static void
117 w32_raise_in_main (void)
118 {
119 DWORD threadid;
120
121 DEBUGd ("w32_raise_in_main with signal %d", w32_signal_to_raise);
122 raise (w32_signal_to_raise);
123 DEBUGd ("w32_raise_in_main signal %d returned a value",
124 w32_signal_to_raise);
125
126 DEBUGs ("attempting to restore main to pre-signal configuration");
127 if (w32_restore_thread != NULL) /* Catch leaky threads */
128 CloseHandle (w32_restore_thread);
129 w32_restore_thread = CreateThread (NULL, 10000, w32_reset_context,
130 &w32_signal_context, 0, &threadid);
131 if (w32_restore_thread == NULL)
132 {
133 fprintf (stderr, "w32_raise_in_main couldn't create thread\n");
134 fflush (stderr);
135 }
136 else
137 {
138 DEBUGs ("waiting to restore raise context");
139 WaitForSingleObject (w32_restore_thread, INFINITE);
140 fprintf (stderr, "w32_raise_in_main couldn't restore context\n");
141 fflush (stderr);
142 }
143 }
144
145 void
146 w32_raise_final (void)
147 {
148 CloseHandle (w32_main_thread);
149 if (w32_restore_thread != NULL) /* Catch leaky threads */
150 CloseHandle (w32_restore_thread);
151 w32_main_thread = w32_restore_thread = NULL;
152 }
153
154 /* Raise the given signal in the main thread. w32_raise_init ()
155 must have been called from the main thread already. */
156 void
157 w32_raise (int sig)
158 {
159 int ret;
160
161 if (w32_in_main_thread ())
162 {
163 /* Called from main thread -- a simple raise () should work. */
164 DEBUGd ("raising signal %d within main", signal);
165 raise (sig);
166 DEBUGd ("returning from signal %d within main", signal);
167 }
168 else
169 {
170 /* Called from alternate thread -- call w32_raise_in_main in the
171 main thread with w32_signal_to_raise set to the signal */
172 CONTEXT raise_context;
173 DEBUGd ("raising signal %d from separate thread", signal);
174
175 /* Suspend main and remember the context. */
176 SuspendThread (w32_main_thread);
177 /* X86 code */
178 w32_signal_context.ContextFlags
179 = CONTEXT_FULL|CONTEXT_FLOATING_POINT|CONTEXT_DEBUG_REGISTERS;
180 GetThreadContext (w32_main_thread, &w32_signal_context);
181
182 /* Change the context to w32_raise_in_main. The
183 context.Eip=&fn trick for setting the program counter is
184 courtesy of
185
186 http://fit.c2.com/files/LispPlatform/lisp/clisp-2.28/src/win32aux.d
187
188 Auxiliary functions for CLISP on Win32, Bruno Haible
189 1997-1999. */
190
191 memcpy (&raise_context, &w32_signal_context, sizeof (CONTEXT));
192 raise_context.Eip = (DWORD)&w32_raise_in_main; /* X86 code */
193 w32_signal_to_raise = sig;
194 SetThreadContext (w32_main_thread, &raise_context);
195
196 /* Resume main at w32_raise_in_main */
197 ret = ResumeThread (w32_main_thread);
198 DEBUGd ("main resumed at w32_raise_in_main with suspend count %d",
199 ret);
200 }
201 }
202
203 void
204 w32_sigint_init (void)
205 {
206 /* Capture main context */
207 w32_main_thread_id = GetCurrentThreadId ();
208 DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
209 GetCurrentProcess (), &w32_main_thread,
210 0, FALSE, DUPLICATE_SAME_ACCESS);
211
212 InitializeCriticalSectionAndSpinCount (&w32_thread_setjmp_mutex, 0);
213 }
214
215 #endif /* #if defined (__WIN32__) && ! defined (_POSIX_VERSION) */
46 216
47 void 217 void
48 octave_jump_to_enclosing_context (void) 218 octave_jump_to_enclosing_context (void)
49 { 219 {
50 #if defined (OCTAVE_HAVE_SIG_JUMP) 220 #if defined (OCTAVE_HAVE_SIG_JUMP)