9907
|
1 /* Process support for Windows NT port of GNU EMACS.
|
|
2 Copyright (C) 1992 Free Software Foundation, Inc.
|
|
3
|
|
4 This file is part of GNU Emacs.
|
|
5
|
|
6 GNU Emacs is free software; you can redistribute it and/or modify it
|
|
7 under the terms of the GNU General Public License as published by the
|
|
8 Free Software Foundation; either version 2, or (at your option) any later
|
|
9 version.
|
|
10
|
|
11 GNU Emacs is distributed in the hope that it will be useful, but WITHOUT
|
|
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
14 more details.
|
|
15
|
|
16 You should have received a copy of the GNU General Public License along
|
|
17 with GNU Emacs; see the file COPYING. If not, write to the Free Software
|
|
18 Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
19
|
|
20 Drew Bliss Oct 14, 1993
|
|
21 Adapted from alarm.c by Tim Fleehart
|
|
22 */
|
|
23
|
|
24 #include <stdio.h>
|
|
25 #include <stdlib.h>
|
|
26 #include <errno.h>
|
|
27 #include <io.h>
|
|
28 #include <signal.h>
|
|
29
|
|
30 #include "config.h"
|
|
31
|
|
32 #include <windows.h>
|
|
33
|
|
34 #include "lisp.h"
|
|
35 #include "nt.h"
|
|
36 #include "systime.h"
|
|
37
|
|
38 /* #define FULL_DEBUG */
|
|
39
|
|
40 typedef void (_CALLBACK_ *signal_handler)(int);
|
|
41
|
|
42 /* Defined in process.h which conflicts with the local copy */
|
|
43 #define _P_NOWAIT 1
|
|
44
|
|
45 typedef struct _child_process
|
|
46 {
|
|
47 int fd;
|
|
48 HANDLE char_avail;
|
|
49 HANDLE char_consumed;
|
|
50 char chr;
|
|
51 BOOL status;
|
|
52 HANDLE process;
|
|
53 DWORD pid;
|
|
54 HANDLE thrd;
|
|
55 } child_process;
|
|
56
|
|
57 #define MAX_CHILDREN MAXDESC
|
|
58
|
|
59 #ifdef EMACSDEBUG
|
|
60 void _CRTAPI1
|
|
61 _DebPrint (char *fmt, ...)
|
|
62 {
|
|
63 char buf[256];
|
|
64 va_list args;
|
|
65
|
|
66 va_start (args, fmt);
|
|
67 vsprintf (buf, fmt, args);
|
|
68 va_end (args);
|
|
69 OutputDebugString (buf);
|
|
70 }
|
|
71 #endif
|
|
72
|
|
73 /* Child process management list. */
|
|
74 static int child_proc_count = 0;
|
|
75 static child_process child_procs[MAX_CHILDREN];
|
|
76 static child_process *dead_child = NULL;
|
|
77
|
|
78 #define CHILD_ACTIVE(cp) ((cp)->process != NULL)
|
|
79 #define DEACTIVATE_CHILD(cp) ((cp)->process = NULL)
|
|
80
|
|
81 /* Signal handlers...SIG_DFL == 0 so this is initialized correctly. */
|
|
82 static signal_handler sig_handlers[NSIG];
|
|
83
|
|
84 /* Fake signal implementation to record the SIGCHLD handler. */
|
|
85 signal_handler
|
|
86 win32_signal (int sig, signal_handler handler)
|
|
87 {
|
|
88 signal_handler old;
|
|
89
|
|
90 if (sig != SIGCHLD)
|
|
91 {
|
|
92 errno = EINVAL;
|
|
93 return SIG_ERR;
|
|
94 }
|
|
95 old = sig_handlers[sig];
|
|
96 sig_handlers[sig] = handler;
|
|
97 return old;
|
|
98 }
|
|
99
|
|
100 /* Find an unused process slot. */
|
|
101 static child_process *
|
|
102 new_child (void)
|
|
103 {
|
|
104 child_process *cp;
|
|
105
|
|
106 if (child_proc_count == MAX_CHILDREN)
|
|
107 return NULL;
|
|
108
|
|
109 for (cp = child_procs+(child_proc_count-1); cp >= child_procs; cp--)
|
|
110 if (!CHILD_ACTIVE (cp))
|
|
111 return cp;
|
|
112 return &child_procs[child_proc_count++];
|
|
113 }
|
|
114
|
|
115 /* Find a child by pid. */
|
|
116 static child_process *
|
|
117 find_child_pid (DWORD pid)
|
|
118 {
|
|
119 child_process *cp;
|
|
120
|
|
121 for (cp = child_procs+(child_proc_count-1); cp >= child_procs; cp--)
|
|
122 if (CHILD_ACTIVE (cp) && pid == cp->pid)
|
|
123 return cp;
|
|
124 return NULL;
|
|
125 }
|
|
126
|
|
127 /* Find a child by fd. */
|
|
128 static child_process *
|
|
129 find_child_fd (int fd)
|
|
130 {
|
|
131 child_process *cp;
|
|
132
|
|
133 for (cp = child_procs+(child_proc_count-1); cp >= child_procs; cp--)
|
|
134 if (CHILD_ACTIVE (cp) && fd == cp->fd)
|
|
135 return cp;
|
|
136 return NULL;
|
|
137 }
|
|
138
|
|
139 /* Thread proc for child process reader threads
|
|
140 The threads just sit in a loop waiting for input
|
|
141 When they detect input, they signal the char_avail input to
|
|
142 wake up the select emulator
|
|
143 When the select emulator processes their input, it pulses
|
|
144 char_consumed so that the reader thread goes back to reading. */
|
|
145 DWORD WINAPI
|
|
146 reader_thread (void *arg)
|
|
147 {
|
|
148 child_process *cp;
|
|
149
|
|
150 /* Our identity */
|
|
151 cp = (child_process *)arg;
|
|
152
|
|
153 /* We have to wait for the go-ahead before we can start */
|
|
154 if (WaitForSingleObject (cp->char_consumed, INFINITE) != WAIT_OBJECT_0)
|
|
155 return 0;
|
|
156 /* If something went wrong, quit */
|
|
157 if (!cp->status)
|
|
158 return 0;
|
|
159
|
|
160 for (;;)
|
|
161 {
|
|
162 /* Use read to get CRLF translation */
|
|
163 if (read (cp->fd, &cp->chr, sizeof (char)) == sizeof (char))
|
|
164 {
|
|
165 cp->status = TRUE;
|
|
166 }
|
|
167 else
|
|
168 {
|
|
169 #ifdef FULL_DEBUG
|
|
170 DebPrint (("reader_thread.read failed with %lu for fd %ld\n",
|
|
171 GetLastError (), cp->fd));
|
|
172 #endif
|
|
173 cp->status = FALSE;
|
|
174 }
|
|
175
|
|
176 if (!SetEvent (cp->char_avail))
|
|
177 {
|
|
178 DebPrint (("reader_thread.SetEvent failed with %lu for fd %ld\n",
|
|
179 GetLastError (), cp->fd));
|
|
180 break;
|
|
181 }
|
|
182
|
|
183 /* If the read died, the child has died so let the thread die */
|
|
184 if (!cp->status)
|
|
185 break;
|
|
186
|
|
187 /* Wait until our input is acknowledged before reading again */
|
|
188 if (WaitForSingleObject (cp->char_consumed, INFINITE) != WAIT_OBJECT_0)
|
|
189 {
|
|
190 DebPrint (("reader_thread.WaitForSingleObject failed with "
|
|
191 "%lu for fd %ld\n", GetLastError (), cp->fd));
|
|
192 break;
|
|
193 }
|
|
194 }
|
|
195 return 0;
|
|
196 }
|
|
197
|
|
198 static BOOL
|
|
199 create_child (char *exe, char *cmdline, char *env,
|
|
200 PROCESS_INFORMATION *info)
|
|
201 {
|
|
202 child_process *cp;
|
|
203 DWORD id;
|
|
204 STARTUPINFO start;
|
|
205 SECURITY_ATTRIBUTES sec_attrs;
|
|
206 SECURITY_DESCRIPTOR sec_desc;
|
|
207
|
|
208 cp = new_child ();
|
|
209 if (cp == NULL)
|
|
210 goto EH_Fail;
|
|
211
|
|
212 cp->fd = -1;
|
|
213
|
|
214 cp->char_avail = CreateEvent (NULL, FALSE, FALSE, NULL);
|
|
215 if (cp->char_avail == NULL)
|
|
216 goto EH_Fail;
|
|
217
|
|
218 cp->char_consumed = CreateEvent (NULL, FALSE, FALSE, NULL);
|
|
219 if (cp->char_consumed == NULL)
|
|
220 goto EH_char_avail;
|
|
221
|
|
222 cp->thrd = CreateThread (NULL, 1024, reader_thread, cp, 0, &id);
|
|
223 if (cp->thrd == NULL)
|
|
224 goto EH_char_consumed;
|
|
225
|
|
226 memset (&start, 0, sizeof (start));
|
|
227 start.cb = sizeof (start);
|
|
228
|
|
229 /* Explicitly specify no security */
|
|
230 if (!InitializeSecurityDescriptor (&sec_desc, SECURITY_DESCRIPTOR_REVISION))
|
|
231 goto EH_thrd;
|
|
232 if (!SetSecurityDescriptorDacl (&sec_desc, TRUE, NULL, FALSE))
|
|
233 goto EH_thrd;
|
|
234 sec_attrs.nLength = sizeof (sec_attrs);
|
|
235 sec_attrs.lpSecurityDescriptor = &sec_desc;
|
|
236 sec_attrs.bInheritHandle = FALSE;
|
|
237
|
|
238 if (!CreateProcess (exe, cmdline, &sec_attrs, NULL, TRUE,
|
|
239 CREATE_NEW_PROCESS_GROUP, env, NULL,
|
|
240 &start, info))
|
|
241 goto EH_thrd;
|
|
242 cp->process = info->hProcess;
|
|
243 cp->pid = info->dwProcessId;
|
|
244
|
|
245 return TRUE;
|
|
246
|
|
247 EH_thrd:
|
|
248 id = GetLastError ();
|
|
249
|
|
250 cp->status = FALSE;
|
|
251 SetEvent (cp->char_consumed);
|
|
252 EH_char_consumed:
|
|
253 CloseHandle (cp->char_consumed);
|
|
254 EH_char_avail:
|
|
255 CloseHandle (cp->char_avail);
|
|
256 EH_Fail:
|
|
257 return FALSE;
|
|
258 }
|
|
259
|
|
260 /* create_child doesn't know what emacs' file handle will be for waiting
|
|
261 on output from the child, so we need to make this additional call
|
|
262 to register the handle with the process
|
|
263 This way the select emulator knows how to match file handles with
|
|
264 entries in child_procs. */
|
|
265 void
|
|
266 register_child (int pid, int fd)
|
|
267 {
|
|
268 child_process *cp;
|
|
269
|
|
270 cp = find_child_pid (pid);
|
|
271 if (cp == NULL)
|
|
272 {
|
|
273 DebPrint (("register_child unable to find pid %lu\n", pid));
|
|
274 return;
|
|
275 }
|
|
276
|
|
277 #ifdef FULL_DEBUG
|
|
278 DebPrint (("register_child registered fd %d with pid %lu\n", fd, pid));
|
|
279 #endif
|
|
280
|
|
281 cp->fd = fd;
|
|
282 cp->status = TRUE;
|
|
283
|
|
284 /* Tell the reader thread to start */
|
|
285 if (!SetEvent (cp->char_consumed))
|
|
286 {
|
|
287 DebPrint (("register_child.SetEvent failed with %lu for fd %ld\n",
|
|
288 GetLastError (), cp->fd));
|
|
289 }
|
|
290 }
|
|
291
|
|
292 /* When a process dies its pipe will break so the reader thread will
|
|
293 signal failure to the select emulator.
|
|
294 The select emulator then calls this routine to clean up.
|
|
295 Since the thread signaled failure we can assume it is exiting. */
|
|
296 static void
|
|
297 remove_child (child_process *cp)
|
|
298 {
|
|
299 /* Reap the thread */
|
|
300 if (WaitForSingleObject (cp->thrd, INFINITE) != WAIT_OBJECT_0)
|
|
301 {
|
|
302 DebPrint (("remove_child.WaitForSingleObject (thread) failed "
|
|
303 "with %lu for fd %ld\n", GetLastError (), cp->fd));
|
|
304 }
|
|
305 CloseHandle (cp->thrd);
|
|
306 CloseHandle (cp->char_consumed);
|
|
307 CloseHandle (cp->char_avail);
|
|
308
|
|
309 /* Reap the process */
|
|
310 if (WaitForSingleObject (cp->process, INFINITE) != WAIT_OBJECT_0)
|
|
311 {
|
|
312 DebPrint (("remove_child.WaitForSingleObject (process) failed "
|
|
313 "with %lu for fd %ld\n", GetLastError (), cp->fd));
|
|
314 }
|
|
315 CloseHandle (cp->process);
|
|
316
|
|
317 DEACTIVATE_CHILD (cp);
|
|
318 }
|
|
319
|
|
320 /* Wait for any of our existing child processes to die
|
|
321 When it does, close its handle
|
|
322 Return the pid and fill in the status if non-NULL. */
|
|
323 int
|
|
324 win32_wait (int *status)
|
|
325 {
|
|
326 DWORD active, retval;
|
|
327 int nh;
|
|
328 child_process *cp, *cps[MAX_CHILDREN];
|
|
329 HANDLE wait_hnd[MAX_CHILDREN];
|
|
330
|
|
331 nh = 0;
|
|
332 if (dead_child != NULL)
|
|
333 {
|
|
334 /* We want to wait for a specific child */
|
|
335 wait_hnd[nh] = dead_child->process;
|
|
336 cps[nh] = dead_child;
|
|
337 nh++;
|
|
338 }
|
|
339 else
|
|
340 {
|
|
341 for (cp = child_procs+(child_proc_count-1); cp >= child_procs; cp--)
|
|
342 if (CHILD_ACTIVE (cp))
|
|
343 {
|
|
344 wait_hnd[nh] = cp->process;
|
|
345 cps[nh] = cp;
|
|
346 nh++;
|
|
347 }
|
|
348 }
|
|
349
|
|
350 if (nh == 0)
|
|
351 {
|
|
352 /* Nothing to wait on, so fail */
|
|
353 errno = ECHILD;
|
|
354 return -1;
|
|
355 }
|
|
356
|
|
357 active = WaitForMultipleObjects (nh, wait_hnd, FALSE, INFINITE);
|
|
358 if (active == WAIT_FAILED)
|
|
359 {
|
|
360 errno = EBADF;
|
|
361 return -1;
|
|
362 }
|
|
363 else if (active == WAIT_TIMEOUT)
|
|
364 {
|
|
365 /* Should never happen */
|
|
366 errno = EINVAL;
|
|
367 return -1;
|
|
368 }
|
|
369 else if (active >= WAIT_OBJECT_0 &&
|
|
370 active < WAIT_OBJECT_0+MAXIMUM_WAIT_OBJECTS)
|
|
371 {
|
|
372 active -= WAIT_OBJECT_0;
|
|
373 }
|
|
374 else if (active >= WAIT_ABANDONED_0 &&
|
|
375 active < WAIT_ABANDONED_0+MAXIMUM_WAIT_OBJECTS)
|
|
376 {
|
|
377 active -= WAIT_ABANDONED_0;
|
|
378 }
|
|
379
|
|
380 if (!GetExitCodeProcess (wait_hnd[active], &retval))
|
|
381 {
|
|
382 DebPrint (("Wait.GetExitCodeProcess failed with %lu\n",
|
|
383 GetLastError ()));
|
|
384 retval = 1;
|
|
385 }
|
|
386 if (retval == STILL_ACTIVE)
|
|
387 {
|
|
388 /* Should never happen */
|
|
389 DebPrint (("Wait.WaitForMultipleObjects returned an active process\n"));
|
|
390 errno = EINVAL;
|
|
391 return -1;
|
|
392 }
|
|
393
|
|
394 cp = cps[active];
|
|
395 #ifdef FULL_DEBUG
|
|
396 DebPrint (("Wait signaled with process pid %d\n", cp->pid));
|
|
397 #endif
|
|
398
|
|
399 if (status)
|
|
400 {
|
|
401 /* In process.c the default WAITTYPE is defined.
|
|
402 Since we can't determine anything about why a process died
|
|
403 we can only return a code that looks like WIFEXITED */
|
|
404 *status = (retval & 0x7fffff) << 8;
|
|
405 }
|
|
406
|
|
407 return cp->pid;
|
|
408 }
|
|
409
|
|
410 /* We pass our process ID to our children by setting up an environment
|
|
411 variable in their environment. */
|
|
412 char ppid_env_var_buffer[64];
|
|
413
|
|
414 /* When a new child process is created we need to register it in our list,
|
|
415 so intercept spawn requests. */
|
|
416 int
|
|
417 win32_spawnve (int mode, char *cmdname, char **argv, char **envp)
|
|
418 {
|
|
419 char *cmdline, *env, *parg, **targ;
|
|
420 int arglen;
|
|
421 PROCESS_INFORMATION pi;
|
|
422
|
|
423 if (child_proc_count == MAX_CHILDREN)
|
|
424 {
|
|
425 errno = EAGAIN;
|
|
426 return -1;
|
|
427 }
|
|
428
|
|
429 /* We don't care about the other modes */
|
|
430 if (mode != _P_NOWAIT)
|
|
431 {
|
|
432 errno = EINVAL;
|
|
433 return -1;
|
|
434 }
|
|
435
|
|
436 /* we have to do some conjuring here to put argv and envp into the
|
|
437 form CreateProcess wants... argv needs to be a space separated/null
|
|
438 terminated list of parameters, and envp is a null
|
|
439 separated/double-null terminated list of parameters.
|
|
440
|
|
441 Since I have no idea how large argv and envp are likely to be
|
|
442 we figure out list lengths on the fly and allocate them. */
|
|
443
|
|
444 /* do argv... */
|
|
445 arglen = 0;
|
|
446 targ = argv;
|
|
447 while (*targ)
|
|
448 {
|
|
449 arglen += strlen (*targ++) + 1;
|
|
450 }
|
|
451 cmdline = malloc (arglen);
|
|
452 if (cmdline == NULL)
|
|
453 {
|
|
454 errno = ENOMEM;
|
|
455 goto EH_Fail;
|
|
456 }
|
|
457 targ = argv;
|
|
458 parg = cmdline;
|
|
459 while (*targ)
|
|
460 {
|
|
461 strcpy (parg, *targ);
|
|
462 parg += strlen (*targ++);
|
|
463 *parg++ = ' ';
|
|
464 }
|
|
465 *--parg = '\0';
|
|
466
|
|
467 /* and envp... */
|
|
468 arglen = 1;
|
|
469 targ = envp;
|
|
470 while (*targ)
|
|
471 {
|
|
472 arglen += strlen (*targ++) + 1;
|
|
473 }
|
|
474 sprintf (ppid_env_var_buffer, "__PARENT_PROCESS_ID=%d",
|
|
475 GetCurrentProcessId ());
|
|
476 arglen += strlen (ppid_env_var_buffer) + 1;
|
|
477
|
|
478 env = malloc (arglen);
|
|
479 if (env == NULL)
|
|
480 {
|
|
481 errno = ENOMEM;
|
|
482 goto EH_cmdline;
|
|
483 }
|
|
484 targ = envp;
|
|
485 parg = env;
|
|
486 while (*targ)
|
|
487 {
|
|
488 strcpy (parg, *targ);
|
|
489 parg += strlen (*targ++);
|
|
490 *parg++ = '\0';
|
|
491 }
|
|
492 strcpy (parg, ppid_env_var_buffer);
|
|
493 parg += strlen (ppid_env_var_buffer);
|
|
494 *parg++ = '\0';
|
|
495 *parg = '\0';
|
|
496
|
|
497 /* Now create the process. */
|
|
498 if (!create_child (cmdname, cmdline, env, &pi))
|
|
499 {
|
|
500 errno = ENOEXEC;
|
|
501 goto EH_env;
|
|
502 }
|
|
503
|
|
504 return pi.dwProcessId;
|
|
505
|
|
506 EH_env:
|
|
507 free (env);
|
|
508 EH_cmdline:
|
|
509 free (cmdline);
|
|
510 EH_Fail:
|
|
511 return -1;
|
|
512 }
|
|
513
|
|
514 /* Emulate the select call
|
|
515 Wait for available input on any of the given rfds, or timeout if
|
|
516 a timeout is given and no input is detected
|
|
517 wfds and efds are not supported and must be NULL. */
|
|
518
|
|
519 /* From ntterm.c */
|
|
520 extern HANDLE keyboard_handle;
|
|
521 /* From process.c */
|
|
522 extern int proc_buffered_char[];
|
|
523
|
|
524 int
|
|
525 select (int nfds, SELECT_TYPE *rfds, SELECT_TYPE *wfds, SELECT_TYPE *efds,
|
|
526 EMACS_TIME *timeout)
|
|
527 {
|
|
528 SELECT_TYPE orfds;
|
|
529 DWORD timeout_ms;
|
|
530 int i, nh, nr;
|
|
531 DWORD active;
|
|
532 child_process *cp, *cps[MAX_CHILDREN];
|
|
533 HANDLE wait_hnd[MAX_CHILDREN];
|
|
534
|
|
535 /* If the descriptor sets are NULL but timeout isn't, then just Sleep. */
|
|
536 if (rfds == NULL && wfds == NULL && efds == NULL && timeout != NULL)
|
|
537 {
|
|
538 Sleep ((*timeout) * 1000);
|
|
539 return 0;
|
|
540 }
|
|
541
|
|
542 /* Otherwise, we only handle rfds, so fail otherwise. */
|
|
543 if (rfds == NULL || wfds != NULL || efds != NULL)
|
|
544 {
|
|
545 errno = EINVAL;
|
|
546 return -1;
|
|
547 }
|
|
548
|
|
549 orfds = *rfds;
|
|
550 FD_ZERO (rfds);
|
|
551 nr = 0;
|
|
552
|
|
553 /* Build a list of handles to wait on. */
|
|
554 nh = 0;
|
|
555 for (i = 0; i < nfds; i++)
|
|
556 if (FD_ISSET (i, &orfds))
|
|
557 {
|
|
558 if (i == 0)
|
|
559 {
|
|
560 /* Handle stdin specially */
|
|
561 wait_hnd[nh] = keyboard_handle;
|
|
562 cps[nh] = NULL;
|
|
563 nh++;
|
|
564
|
|
565 /* Check for any emacs-generated input in the queue since
|
|
566 it won't be detected in the wait */
|
|
567 if (detect_input_pending ())
|
|
568 {
|
|
569 FD_SET (i, rfds);
|
|
570 nr++;
|
|
571 }
|
|
572 }
|
|
573 else
|
|
574 {
|
|
575 /* Child process input */
|
|
576 cp = find_child_fd (i);
|
|
577 if (cp)
|
|
578 {
|
|
579 #ifdef FULL_DEBUG
|
|
580 DebPrint (("select waiting on child %d fd %d\n",
|
|
581 cp-child_procs, i));
|
|
582 #endif
|
|
583 wait_hnd[nh] = cp->char_avail;
|
|
584 cps[nh] = cp;
|
|
585 nh++;
|
|
586 }
|
|
587 else
|
|
588 {
|
|
589 /* Unable to find something to wait on for this fd, fail */
|
|
590 DebPrint (("select unable to find child process "
|
|
591 "for fd %ld\n", i));
|
|
592 nh = 0;
|
|
593 break;
|
|
594 }
|
|
595 }
|
|
596 }
|
|
597
|
|
598 /* Nothing to look for, so we didn't find anything */
|
|
599 if (nh == 0)
|
|
600 {
|
|
601 Sleep ((*timeout) * 1000);
|
|
602 return 0;
|
|
603 }
|
|
604
|
|
605 /* Check for immediate return without waiting */
|
|
606 if (nr > 0)
|
|
607 return nr;
|
|
608
|
|
609 /*
|
|
610 Wait for input
|
|
611 If a child process dies while this is waiting, its pipe will break
|
|
612 so the reader thread will signal an error condition, thus, the wait
|
|
613 will wake up
|
|
614 */
|
|
615 timeout_ms = timeout ? *timeout*1000 : INFINITE;
|
|
616 active = WaitForMultipleObjects (nh, wait_hnd, FALSE, timeout_ms);
|
|
617 if (active == WAIT_FAILED)
|
|
618 {
|
|
619 DebPrint (("select.WaitForMultipleObjects (%d, %lu) failed with %lu\n",
|
|
620 nh, timeout_ms, GetLastError ()));
|
|
621 /* Is there a better error? */
|
|
622 errno = EBADF;
|
|
623 return -1;
|
|
624 }
|
|
625 else if (active == WAIT_TIMEOUT)
|
|
626 {
|
|
627 return 0;
|
|
628 }
|
|
629 else if (active >= WAIT_OBJECT_0 &&
|
|
630 active < WAIT_OBJECT_0+MAXIMUM_WAIT_OBJECTS)
|
|
631 {
|
|
632 active -= WAIT_OBJECT_0;
|
|
633 }
|
|
634 else if (active >= WAIT_ABANDONED_0 &&
|
|
635 active < WAIT_ABANDONED_0+MAXIMUM_WAIT_OBJECTS)
|
|
636 {
|
|
637 active -= WAIT_ABANDONED_0;
|
|
638 }
|
|
639
|
|
640 if (cps[active] == NULL)
|
|
641 {
|
|
642 /* Keyboard input available */
|
|
643 FD_SET (0, rfds);
|
|
644 nr++;
|
|
645
|
|
646 /* This shouldn't be necessary, but apparently just setting the input
|
|
647 fd is not good enough for emacs */
|
|
648 read_input_waiting ();
|
|
649 }
|
|
650 else
|
|
651 {
|
|
652 /* Child process */
|
|
653 cp = cps[active];
|
|
654
|
|
655 /* If status is FALSE the read failed so don't report input */
|
|
656 if (cp->status)
|
|
657 {
|
|
658 FD_SET (cp->fd, rfds);
|
|
659 proc_buffered_char[cp->fd] = cp->chr;
|
|
660 nr++;
|
|
661 }
|
|
662 else
|
|
663 {
|
|
664 /* The SIGCHLD handler will do a Wait so we know it won't
|
|
665 return until the process is dead
|
|
666 We force Wait to only wait for this process to avoid it
|
|
667 picking up other children that happen to be dead but that
|
|
668 we haven't noticed yet
|
|
669 SIG_DFL for SIGCHLD is ignore? */
|
|
670 if (sig_handlers[SIGCHLD] != SIG_DFL &&
|
|
671 sig_handlers[SIGCHLD] != SIG_IGN)
|
|
672 {
|
|
673 #ifdef FULL_DEBUG
|
|
674 DebPrint (("select calling SIGCHLD handler for pid %d\n",
|
|
675 cp->pid));
|
|
676 #endif
|
|
677 dead_child = cp;
|
|
678 sig_handlers[SIGCHLD](SIGCHLD);
|
|
679 dead_child = NULL;
|
|
680 }
|
|
681
|
|
682 /* Clean up the child process entry in the table */
|
|
683 remove_child (cp);
|
|
684 }
|
|
685 }
|
|
686 return nr;
|
|
687 }
|
|
688
|
|
689 /*
|
|
690 Substitute for certain kill () operations
|
|
691 */
|
|
692 int
|
|
693 win32_kill_process (int pid, int sig)
|
|
694 {
|
|
695 child_process *cp;
|
|
696
|
|
697 /* Only handle signals that will result in the process dying */
|
|
698 if (sig != SIGINT && sig != SIGKILL && sig != SIGQUIT && sig != SIGHUP)
|
|
699 {
|
|
700 errno = EINVAL;
|
|
701 return -1;
|
|
702 }
|
|
703
|
|
704 cp = find_child_pid (pid);
|
|
705 if (cp == NULL)
|
|
706 {
|
|
707 DebPrint (("win32_kill_process didn't find a child with pid %lu\n", pid));
|
|
708 errno = ECHILD;
|
|
709 return -1;
|
|
710 }
|
|
711
|
|
712 if (sig == SIGINT)
|
|
713 {
|
|
714 /* Fake Ctrl-Break. */
|
|
715 if (!GenerateConsoleCtrlEvent (CTRL_BREAK_EVENT, pid))
|
|
716 {
|
|
717 DebPrint (("win32_kill_process.GenerateConsoleCtrlEvent return %d "
|
|
718 "for pid %lu\n", GetLastError (), pid));
|
|
719 errno = EINVAL;
|
|
720 return -1;
|
|
721 }
|
|
722 }
|
|
723 else
|
|
724 {
|
|
725 /* Kill the process. On Win32 this doesn't kill child processes
|
|
726 so it doesn't work very well for shells which is why it's
|
|
727 not used in every case. */
|
|
728 if (!TerminateProcess (cp->process, 0xff))
|
|
729 {
|
|
730 DebPrint (("win32_kill_process.TerminateProcess returned %d "
|
|
731 "for pid %lu\n", GetLastError (), pid));
|
|
732 errno = EINVAL;
|
|
733 return -1;
|
|
734 }
|
|
735 }
|
|
736 return 0;
|
|
737 }
|
|
738
|
|
739 /* If the channel is a pipe this read might block since we don't
|
|
740 know how many characters are available, so check and read only
|
|
741 what's there
|
|
742 We also need to wake up the reader thread once we've read our data. */
|
|
743 int
|
|
744 read_child_output (int fd, char *buf, int max)
|
|
745 {
|
|
746 HANDLE h;
|
|
747 int to_read, nchars;
|
|
748 DWORD waiting;
|
|
749 child_process *cp;
|
|
750
|
|
751 h = (HANDLE)_get_osfhandle (fd);
|
|
752 if (GetFileType (h) == FILE_TYPE_PIPE)
|
|
753 {
|
|
754 PeekNamedPipe (h, NULL, 0, NULL, &waiting, NULL);
|
|
755 to_read = min (waiting, (DWORD)max);
|
|
756 }
|
|
757 else
|
|
758 to_read = max;
|
|
759
|
|
760 /* Use read to get CRLF translation */
|
|
761 nchars = read (fd, buf, to_read);
|
|
762
|
|
763 if (GetFileType (h) == FILE_TYPE_PIPE)
|
|
764 {
|
|
765 /* Wake up the reader thread
|
|
766 for this process */
|
|
767 cp = find_child_fd (fd);
|
|
768 if (cp)
|
|
769 {
|
|
770 if (!SetEvent (cp->char_consumed))
|
|
771 DebPrint (("read_child_output.SetEvent failed with "
|
|
772 "%lu for fd %ld\n", GetLastError (), fd));
|
|
773 }
|
|
774 else
|
|
775 DebPrint (("read_child_output couldn't find a child with fd %d\n",
|
|
776 fd));
|
|
777 }
|
|
778
|
|
779 return nchars;
|
|
780 }
|