aboutsummaryrefslogtreecommitdiffstats
path: root/src/w32proc.c
diff options
context:
space:
mode:
authorEli Zaretskii2012-11-17 20:00:16 +0200
committerEli Zaretskii2012-11-17 20:00:16 +0200
commitcf2d22b874ca2df0072e32ee641e8efffe4abd6d (patch)
tree1795142ec7861fc85c61adc90f03265b69041556 /src/w32proc.c
parent3c4ca7155293ffc2d04708007131bcbc882d8913 (diff)
parent6ad30855c02908fdd99d9b11943719e185e65ee3 (diff)
downloademacs-cf2d22b874ca2df0072e32ee641e8efffe4abd6d.tar.gz
emacs-cf2d22b874ca2df0072e32ee641e8efffe4abd6d.zip
Merge from trunk.
Diffstat (limited to 'src/w32proc.c')
-rw-r--r--src/w32proc.c165
1 files changed, 116 insertions, 49 deletions
diff --git a/src/w32proc.c b/src/w32proc.c
index e074ece020d..2951df7ed89 100644
--- a/src/w32proc.c
+++ b/src/w32proc.c
@@ -431,13 +431,14 @@ timer_loop (LPVOID arg)
431 /* Simulate a signal delivered to the thread which installed 431 /* Simulate a signal delivered to the thread which installed
432 the timer, by suspending that thread while the handler 432 the timer, by suspending that thread while the handler
433 runs. */ 433 runs. */
434 DWORD result = SuspendThread (itimer->caller_thread); 434 HANDLE th = itimer->caller_thread;
435 DWORD result = SuspendThread (th);
435 436
436 if (result == (DWORD)-1) 437 if (result == (DWORD)-1)
437 return 2; 438 return 2;
438 439
439 handler (sig); 440 handler (sig);
440 ResumeThread (itimer->caller_thread); 441 ResumeThread (th);
441 } 442 }
442 443
443 /* Update expiration time and loop. */ 444 /* Update expiration time and loop. */
@@ -562,6 +563,7 @@ static int
562start_timer_thread (int which) 563start_timer_thread (int which)
563{ 564{
564 DWORD exit_code; 565 DWORD exit_code;
566 HANDLE th;
565 struct itimer_data *itimer = 567 struct itimer_data *itimer =
566 (which == ITIMER_REAL) ? &real_itimer : &prof_itimer; 568 (which == ITIMER_REAL) ? &real_itimer : &prof_itimer;
567 569
@@ -570,9 +572,29 @@ start_timer_thread (int which)
570 && exit_code == STILL_ACTIVE) 572 && exit_code == STILL_ACTIVE)
571 return 0; 573 return 0;
572 574
575 /* Clean up after possibly exited thread. */
576 if (itimer->timer_thread)
577 {
578 CloseHandle (itimer->timer_thread);
579 itimer->timer_thread = NULL;
580 }
581 if (itimer->caller_thread)
582 {
583 CloseHandle (itimer->caller_thread);
584 itimer->caller_thread = NULL;
585 }
586
573 /* Start a new thread. */ 587 /* Start a new thread. */
588 if (!DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
589 GetCurrentProcess (), &th, 0, FALSE,
590 DUPLICATE_SAME_ACCESS))
591 {
592 errno = ESRCH;
593 return -1;
594 }
574 itimer->terminate = 0; 595 itimer->terminate = 0;
575 itimer->type = which; 596 itimer->type = which;
597 itimer->caller_thread = th;
576 /* Request that no more than 64KB of stack be reserved for this 598 /* Request that no more than 64KB of stack be reserved for this
577 thread, to avoid reserving too much memory, which would get in 599 thread, to avoid reserving too much memory, which would get in
578 the way of threads we start to wait for subprocesses. See also 600 the way of threads we start to wait for subprocesses. See also
@@ -591,7 +613,7 @@ start_timer_thread (int which)
591 /* This is needed to make sure that the timer thread running for 613 /* This is needed to make sure that the timer thread running for
592 profiling gets CPU as soon as the Sleep call terminates. */ 614 profiling gets CPU as soon as the Sleep call terminates. */
593 if (which == ITIMER_PROF) 615 if (which == ITIMER_PROF)
594 SetThreadPriority (itimer->caller_thread, THREAD_PRIORITY_TIME_CRITICAL); 616 SetThreadPriority (itimer->timer_thread, THREAD_PRIORITY_TIME_CRITICAL);
595 617
596 return 0; 618 return 0;
597} 619}
@@ -626,17 +648,9 @@ getitimer (int which, struct itimerval *value)
626 648
627 itimer = (which == ITIMER_REAL) ? &real_itimer : &prof_itimer; 649 itimer = (which == ITIMER_REAL) ? &real_itimer : &prof_itimer;
628 650
629 if (!DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
630 GetCurrentProcess (), &itimer->caller_thread, 0,
631 FALSE, DUPLICATE_SAME_ACCESS))
632 {
633 errno = ESRCH;
634 return -1;
635 }
636
637 ticks_now = w32_get_timer_time ((which == ITIMER_REAL) 651 ticks_now = w32_get_timer_time ((which == ITIMER_REAL)
638 ? NULL 652 ? NULL
639 : itimer->caller_thread); 653 : GetCurrentThread ());
640 654
641 t_expire = &itimer->expire; 655 t_expire = &itimer->expire;
642 t_reload = &itimer->reload; 656 t_reload = &itimer->reload;
@@ -775,7 +789,6 @@ alarm (int seconds)
775/* Child process management list. */ 789/* Child process management list. */
776int child_proc_count = 0; 790int child_proc_count = 0;
777child_process child_procs[ MAX_CHILDREN ]; 791child_process child_procs[ MAX_CHILDREN ];
778child_process *dead_child = NULL;
779 792
780static DWORD WINAPI reader_thread (void *arg); 793static DWORD WINAPI reader_thread (void *arg);
781 794
@@ -1028,9 +1041,6 @@ create_child (char *exe, char *cmdline, char *env, int is_gui_app,
1028 if (cp->pid < 0) 1041 if (cp->pid < 0)
1029 cp->pid = -cp->pid; 1042 cp->pid = -cp->pid;
1030 1043
1031 /* pid must fit in a Lisp_Int */
1032 cp->pid = cp->pid & INTMASK;
1033
1034 *pPid = cp->pid; 1044 *pPid = cp->pid;
1035 1045
1036 return TRUE; 1046 return TRUE;
@@ -1106,55 +1116,110 @@ reap_subprocess (child_process *cp)
1106 delete_child (cp); 1116 delete_child (cp);
1107} 1117}
1108 1118
1109/* Wait for any of our existing child processes to die 1119/* Wait for a child process specified by PID, or for any of our
1110 When it does, close its handle 1120 existing child processes (if PID is nonpositive) to die. When it
1111 Return the pid and fill in the status if non-NULL. */ 1121 does, close its handle. Return the pid of the process that died
1122 and fill in STATUS if non-NULL. */
1112 1123
1113int 1124pid_t
1114sys_wait (int *status) 1125waitpid (pid_t pid, int *status, int options)
1115{ 1126{
1116 DWORD active, retval; 1127 DWORD active, retval;
1117 int nh; 1128 int nh;
1118 int pid;
1119 child_process *cp, *cps[MAX_CHILDREN]; 1129 child_process *cp, *cps[MAX_CHILDREN];
1120 HANDLE wait_hnd[MAX_CHILDREN]; 1130 HANDLE wait_hnd[MAX_CHILDREN];
1131 DWORD timeout_ms;
1132 int dont_wait = (options & WNOHANG) != 0;
1121 1133
1122 nh = 0; 1134 nh = 0;
1123 if (dead_child != NULL) 1135 /* According to Posix:
1136
1137 PID = -1 means status is requested for any child process.
1138
1139 PID > 0 means status is requested for a single child process
1140 whose pid is PID.
1141
1142 PID = 0 means status is requested for any child process whose
1143 process group ID is equal to that of the calling process. But
1144 since Windows has only a limited support for process groups (only
1145 for console processes and only for the purposes of passing
1146 Ctrl-BREAK signal to them), and since we have no documented way
1147 of determining whether a given process belongs to our group, we
1148 treat 0 as -1.
1149
1150 PID < -1 means status is requested for any child process whose
1151 process group ID is equal to the absolute value of PID. Again,
1152 since we don't support process groups, we treat that as -1. */
1153 if (pid > 0)
1124 { 1154 {
1125 /* We want to wait for a specific child */ 1155 int our_child = 0;
1126 wait_hnd[nh] = dead_child->procinfo.hProcess; 1156
1127 cps[nh] = dead_child; 1157 /* We are requested to wait for a specific child. */
1128 if (!wait_hnd[nh]) emacs_abort (); 1158 for (cp = child_procs + (child_proc_count-1); cp >= child_procs; cp--)
1129 nh++; 1159 {
1130 active = 0; 1160 /* Some child_procs might be sockets; ignore them. Also
1131 goto get_result; 1161 ignore subprocesses whose output is not yet completely
1162 read. */
1163 if (CHILD_ACTIVE (cp)
1164 && cp->procinfo.hProcess
1165 && cp->pid == pid)
1166 {
1167 our_child = 1;
1168 break;
1169 }
1170 }
1171 if (our_child)
1172 {
1173 if (cp->fd < 0 || (fd_info[cp->fd].flags & FILE_AT_EOF) != 0)
1174 {
1175 wait_hnd[nh] = cp->procinfo.hProcess;
1176 cps[nh] = cp;
1177 nh++;
1178 }
1179 else if (dont_wait)
1180 {
1181 /* PID specifies our subprocess, but its status is not
1182 yet available. */
1183 return 0;
1184 }
1185 }
1186 if (nh == 0)
1187 {
1188 /* No such child process, or nothing to wait for, so fail. */
1189 errno = ECHILD;
1190 return -1;
1191 }
1132 } 1192 }
1133 else 1193 else
1134 { 1194 {
1135 for (cp = child_procs + (child_proc_count-1); cp >= child_procs; cp--) 1195 for (cp = child_procs + (child_proc_count-1); cp >= child_procs; cp--)
1136 /* some child_procs might be sockets; ignore them */ 1196 {
1137 if (CHILD_ACTIVE (cp) && cp->procinfo.hProcess 1197 if (CHILD_ACTIVE (cp)
1138 && (cp->fd < 0 || (fd_info[cp->fd].flags & FILE_AT_EOF) != 0)) 1198 && cp->procinfo.hProcess
1139 { 1199 && (cp->fd < 0 || (fd_info[cp->fd].flags & FILE_AT_EOF) != 0))
1140 wait_hnd[nh] = cp->procinfo.hProcess; 1200 {
1141 cps[nh] = cp; 1201 wait_hnd[nh] = cp->procinfo.hProcess;
1142 nh++; 1202 cps[nh] = cp;
1143 } 1203 nh++;
1204 }
1205 }
1206 if (nh == 0)
1207 {
1208 /* Nothing to wait on, so fail. */
1209 errno = ECHILD;
1210 return -1;
1211 }
1144 } 1212 }
1145 1213
1146 if (nh == 0) 1214 if (dont_wait)
1147 { 1215 timeout_ms = 0;
1148 /* Nothing to wait on, so fail */ 1216 else
1149 errno = ECHILD; 1217 timeout_ms = 1000; /* check for quit about once a second. */
1150 return -1;
1151 }
1152 1218
1153 do 1219 do
1154 { 1220 {
1155 /* Check for quit about once a second. */
1156 QUIT; 1221 QUIT;
1157 active = WaitForMultipleObjects (nh, wait_hnd, FALSE, 1000); 1222 active = WaitForMultipleObjects (nh, wait_hnd, FALSE, timeout_ms);
1158 } while (active == WAIT_TIMEOUT); 1223 } while (active == WAIT_TIMEOUT);
1159 1224
1160 if (active == WAIT_FAILED) 1225 if (active == WAIT_FAILED)
@@ -1184,8 +1249,10 @@ get_result:
1184 } 1249 }
1185 if (retval == STILL_ACTIVE) 1250 if (retval == STILL_ACTIVE)
1186 { 1251 {
1187 /* Should never happen */ 1252 /* Should never happen. */
1188 DebPrint (("Wait.WaitForMultipleObjects returned an active process\n")); 1253 DebPrint (("Wait.WaitForMultipleObjects returned an active process\n"));
1254 if (pid > 0 && dont_wait)
1255 return 0;
1189 errno = EINVAL; 1256 errno = EINVAL;
1190 return -1; 1257 return -1;
1191 } 1258 }
@@ -1199,6 +1266,8 @@ get_result:
1199 else 1266 else
1200 retval <<= 8; 1267 retval <<= 8;
1201 1268
1269 if (pid > 0 && active != 0)
1270 emacs_abort ();
1202 cp = cps[active]; 1271 cp = cps[active];
1203 pid = cp->pid; 1272 pid = cp->pid;
1204#ifdef FULL_DEBUG 1273#ifdef FULL_DEBUG
@@ -2004,9 +2073,7 @@ count_children:
2004 DebPrint (("select calling SIGCHLD handler for pid %d\n", 2073 DebPrint (("select calling SIGCHLD handler for pid %d\n",
2005 cp->pid)); 2074 cp->pid));
2006#endif 2075#endif
2007 dead_child = cp;
2008 sig_handlers[SIGCHLD] (SIGCHLD); 2076 sig_handlers[SIGCHLD] (SIGCHLD);
2009 dead_child = NULL;
2010 } 2077 }
2011 } 2078 }
2012 else if (fdindex[active] == -1) 2079 else if (fdindex[active] == -1)