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