comparison src/process-nt.c @ 373:6240c7796c7a r21-2b2

Import from CVS: tag r21-2b2
author cvs
date Mon, 13 Aug 2007 11:04:06 +0200
parents cc15677e0335
children 8626e4521993
comparison
equal deleted inserted replaced
372:49e1ed2d7ed8 373:6240c7796c7a
36 #include <shellapi.h> 36 #include <shellapi.h>
37 #include <signal.h> 37 #include <signal.h>
38 #ifdef HAVE_SOCKETS 38 #ifdef HAVE_SOCKETS
39 #include <winsock.h> 39 #include <winsock.h>
40 #endif 40 #endif
41
42 /* Arbitrary size limit for code fragments passed to run_in_other_process */
43 #define FRAGMENT_CODE_SIZE 32
41 44
42 /* Bound by winnt.el */ 45 /* Bound by winnt.el */
43 Lisp_Object Qnt_quote_process_args; 46 Lisp_Object Qnt_quote_process_args;
44 47
45 /* Implemenation-specific data. Pointed to by Lisp_Process->process_data */ 48 /* Implemenation-specific data. Pointed to by Lisp_Process->process_data */
141 ResumeThread (pmc->h_thread); 144 ResumeThread (pmc->h_thread);
142 } 145 }
143 146
144 /* 147 /*
145 * Run ROUTINE in the context of process determined by H_PROCESS. The 148 * Run ROUTINE in the context of process determined by H_PROCESS. The
146 * routine is passed the address of DATA as parameter. CODE_END is the 149 * routine is passed the address of DATA as parameter. The ROUTINE must
147 * address immediately after ROUTINE's code. DATA_SIZE is the size of 150 * not be longer than ROUTINE_CODE_SIZE bytes. DATA_SIZE is the size of
148 * DATA structure. 151 * DATA structure.
149 * 152 *
150 * Note that the code must be positionally independent, and compiled 153 * Note that the code must be positionally independent, and compiled
151 * without stack checks (they cause implicit calls into CRT so will 154 * without stack checks (they cause implicit calls into CRT so will
152 * fail). DATA should not refer any data in calling process, as both 155 * fail). DATA should not refer any data in calling process, as both
155 * 158 *
156 * Return the value returned by ROUTINE, or (DWORD)-1 if call failed. 159 * Return the value returned by ROUTINE, or (DWORD)-1 if call failed.
157 */ 160 */
158 static DWORD 161 static DWORD
159 run_in_other_process (HANDLE h_process, 162 run_in_other_process (HANDLE h_process,
160 LPTHREAD_START_ROUTINE routine, LPVOID code_end, 163 LPTHREAD_START_ROUTINE routine,
161 LPVOID data, size_t data_size) 164 LPVOID data, size_t data_size)
162 { 165 {
163 process_memory pm; 166 process_memory pm;
164 size_t code_size = (LPBYTE)code_end - (LPBYTE)routine; 167 CONST size_t code_size = FRAGMENT_CODE_SIZE;
165 /* Need at most 3 extra bytes of memory, for data alignment */ 168 /* Need at most 3 extra bytes of memory, for data alignment */
166 size_t total_size = code_size + data_size + 3; 169 size_t total_size = code_size + data_size + 3;
167 LPVOID remote_data; 170 LPVOID remote_data;
168 HANDLE h_thread; 171 HANDLE h_thread;
169 DWORD dw_unused; 172 DWORD dw_unused;
221 * We handle the following signals: 224 * We handle the following signals:
222 * 225 *
223 * SIGKILL, SIGTERM, SIGQUIT, SIGHUP - These four translate to ExitProcess 226 * SIGKILL, SIGTERM, SIGQUIT, SIGHUP - These four translate to ExitProcess
224 * executed by the remote process 227 * executed by the remote process
225 * SIGINT - The remote process is sent CTRL_BREAK_EVENT 228 * SIGINT - The remote process is sent CTRL_BREAK_EVENT
229 *
230 * The MSVC5.0 compiler feels free to re-order functions within a
231 * compilation unit, so we have no way of finding out the size of the
232 * following functions. Therefore these functions must not be larger than
233 * FRAGMENT_CODE_SIZE.
226 */ 234 */
227 235
228 /* 236 /*
229 * Sending SIGKILL 237 * Sending SIGKILL
230 */ 238 */
236 static DWORD WINAPI 244 static DWORD WINAPI
237 sigkill_proc (sigkill_data* data) 245 sigkill_proc (sigkill_data* data)
238 { 246 {
239 (*data->adr_ExitProcess)(255); 247 (*data->adr_ExitProcess)(255);
240 return 1; 248 return 1;
241 }
242
243 /* Watermark in code space */
244 static void
245 sigkill_code_end (void)
246 {
247 } 249 }
248 250
249 /* 251 /*
250 * Sending break or control c 252 * Sending break or control c
251 */ 253 */
259 sigint_proc (sigint_data* data) 261 sigint_proc (sigint_data* data)
260 { 262 {
261 return (*data->adr_GenerateConsoleCtrlEvent) (data->event, 0); 263 return (*data->adr_GenerateConsoleCtrlEvent) (data->event, 0);
262 } 264 }
263 265
264 /* Watermark in code space */
265 static void
266 sigint_code_end (void)
267 {
268 }
269
270 /* 266 /*
271 * Enabling signals 267 * Enabling signals
272 */ 268 */
273 typedef struct 269 typedef struct
274 { 270 {
278 static DWORD WINAPI 274 static DWORD WINAPI
279 sig_enable_proc (sig_enable_data* data) 275 sig_enable_proc (sig_enable_data* data)
280 { 276 {
281 (*data->adr_SetConsoleCtrlHandler) (NULL, FALSE); 277 (*data->adr_SetConsoleCtrlHandler) (NULL, FALSE);
282 return 1; 278 return 1;
283 }
284
285 /* Watermark in code space */
286 static void
287 sig_enable_code_end (void)
288 {
289 } 279 }
290 280
291 /* 281 /*
292 * Send signal SIGNO to process H_PROCESS. 282 * Send signal SIGNO to process H_PROCESS.
293 * Return nonzero if successful. 283 * Return nonzero if successful.
314 case SIGHUP: 304 case SIGHUP:
315 { 305 {
316 sigkill_data d; 306 sigkill_data d;
317 d.adr_ExitProcess = GetProcAddress (h_kernel, "ExitProcess"); 307 d.adr_ExitProcess = GetProcAddress (h_kernel, "ExitProcess");
318 assert (d.adr_ExitProcess); 308 assert (d.adr_ExitProcess);
319 retval = run_in_other_process (h_process, 309 retval = run_in_other_process (h_process, sigkill_proc,
320 sigkill_proc, sigkill_code_end,
321 &d, sizeof (d)); 310 &d, sizeof (d));
322 break; 311 break;
323 } 312 }
324 case SIGINT: 313 case SIGINT:
325 { 314 {
326 sigint_data d; 315 sigint_data d;
327 d.adr_GenerateConsoleCtrlEvent = 316 d.adr_GenerateConsoleCtrlEvent =
328 GetProcAddress (h_kernel, "GenerateConsoleCtrlEvent"); 317 GetProcAddress (h_kernel, "GenerateConsoleCtrlEvent");
329 assert (d.adr_GenerateConsoleCtrlEvent); 318 assert (d.adr_GenerateConsoleCtrlEvent);
330 d.event = CTRL_C_EVENT; 319 d.event = CTRL_C_EVENT;
331 retval = run_in_other_process (h_process, 320 retval = run_in_other_process (h_process, sigint_proc,
332 sigint_proc, sigint_code_end,
333 &d, sizeof (d)); 321 &d, sizeof (d));
334 break; 322 break;
335 } 323 }
336 default: 324 default:
337 assert (0); 325 assert (0);
351 339
352 assert (h_kernel != NULL); 340 assert (h_kernel != NULL);
353 d.adr_SetConsoleCtrlHandler = 341 d.adr_SetConsoleCtrlHandler =
354 GetProcAddress (h_kernel, "SetConsoleCtrlHandler"); 342 GetProcAddress (h_kernel, "SetConsoleCtrlHandler");
355 assert (d.adr_SetConsoleCtrlHandler); 343 assert (d.adr_SetConsoleCtrlHandler);
356 run_in_other_process (h_process, 344 run_in_other_process (h_process, sig_enable_proc,
357 sig_enable_proc, sig_enable_code_end,
358 &d, sizeof (d)); 345 &d, sizeof (d));
359 } 346 }
360 347
361 #pragma warning (default : 4113) 348 #pragma warning (default : 4113)
362 349