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