Mercurial > emacs
annotate src/w32proc.c @ 14911:f736e9cb067e libc-960329 libc-960330 libc-960331 libc-960401 libc-960402 libc-960403 libc-960404 libc-960405 libc-960406 libc-960407 libc-960408
(aux): Delete another duplicate entry.
| author | Doug Evans <dje@gnu.org> |
|---|---|
| date | Fri, 29 Mar 1996 01:49:55 +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 } |
