diff options
Diffstat (limited to 'src/w32proc.c')
| -rw-r--r-- | src/w32proc.c | 127 |
1 files changed, 90 insertions, 37 deletions
diff --git a/src/w32proc.c b/src/w32proc.c index e3c54fe5460..b4f2099f06a 100644 --- a/src/w32proc.c +++ b/src/w32proc.c | |||
| @@ -783,7 +783,6 @@ alarm (int seconds) | |||
| 783 | /* Child process management list. */ | 783 | /* Child process management list. */ |
| 784 | int child_proc_count = 0; | 784 | int child_proc_count = 0; |
| 785 | child_process child_procs[ MAX_CHILDREN ]; | 785 | child_process child_procs[ MAX_CHILDREN ]; |
| 786 | child_process *dead_child = NULL; | ||
| 787 | 786 | ||
| 788 | static DWORD WINAPI reader_thread (void *arg); | 787 | static DWORD WINAPI reader_thread (void *arg); |
| 789 | 788 | ||
| @@ -1036,9 +1035,6 @@ create_child (char *exe, char *cmdline, char *env, int is_gui_app, | |||
| 1036 | if (cp->pid < 0) | 1035 | if (cp->pid < 0) |
| 1037 | cp->pid = -cp->pid; | 1036 | cp->pid = -cp->pid; |
| 1038 | 1037 | ||
| 1039 | /* pid must fit in a Lisp_Int */ | ||
| 1040 | cp->pid = cp->pid & INTMASK; | ||
| 1041 | |||
| 1042 | *pPid = cp->pid; | 1038 | *pPid = cp->pid; |
| 1043 | 1039 | ||
| 1044 | return TRUE; | 1040 | return TRUE; |
| @@ -1114,55 +1110,110 @@ reap_subprocess (child_process *cp) | |||
| 1114 | delete_child (cp); | 1110 | delete_child (cp); |
| 1115 | } | 1111 | } |
| 1116 | 1112 | ||
| 1117 | /* Wait for any of our existing child processes to die | 1113 | /* Wait for a child process specified by PID, or for any of our |
| 1118 | When it does, close its handle | 1114 | existing child processes (if PID is nonpositive) to die. When it |
| 1119 | Return the pid and fill in the status if non-NULL. */ | 1115 | does, close its handle. Return the pid of the process that died |
| 1116 | and fill in STATUS if non-NULL. */ | ||
| 1120 | 1117 | ||
| 1121 | int | 1118 | pid_t |
| 1122 | sys_wait (int *status) | 1119 | waitpid (pid_t pid, int *status, int options) |
| 1123 | { | 1120 | { |
| 1124 | DWORD active, retval; | 1121 | DWORD active, retval; |
| 1125 | int nh; | 1122 | int nh; |
| 1126 | int pid; | ||
| 1127 | child_process *cp, *cps[MAX_CHILDREN]; | 1123 | child_process *cp, *cps[MAX_CHILDREN]; |
| 1128 | HANDLE wait_hnd[MAX_CHILDREN]; | 1124 | HANDLE wait_hnd[MAX_CHILDREN]; |
| 1125 | DWORD timeout_ms; | ||
| 1126 | int dont_wait = (options & WNOHANG) != 0; | ||
| 1129 | 1127 | ||
| 1130 | nh = 0; | 1128 | nh = 0; |
| 1131 | if (dead_child != NULL) | 1129 | /* According to Posix: |
| 1130 | |||
| 1131 | PID = -1 means status is requested for any child process. | ||
| 1132 | |||
| 1133 | PID > 0 means status is requested for a single child process | ||
| 1134 | whose pid is PID. | ||
| 1135 | |||
| 1136 | PID = 0 means status is requested for any child process whose | ||
| 1137 | process group ID is equal to that of the calling process. But | ||
| 1138 | since Windows has only a limited support for process groups (only | ||
| 1139 | for console processes and only for the purposes of passing | ||
| 1140 | Ctrl-BREAK signal to them), and since we have no documented way | ||
| 1141 | of determining whether a given process belongs to our group, we | ||
| 1142 | treat 0 as -1. | ||
| 1143 | |||
| 1144 | PID < -1 means status is requested for any child process whose | ||
| 1145 | process group ID is equal to the absolute value of PID. Again, | ||
| 1146 | since we don't support process groups, we treat that as -1. */ | ||
| 1147 | if (pid > 0) | ||
| 1132 | { | 1148 | { |
| 1133 | /* We want to wait for a specific child */ | 1149 | int our_child = 0; |
| 1134 | wait_hnd[nh] = dead_child->procinfo.hProcess; | 1150 | |
| 1135 | cps[nh] = dead_child; | 1151 | /* We are requested to wait for a specific child. */ |
| 1136 | if (!wait_hnd[nh]) emacs_abort (); | 1152 | for (cp = child_procs + (child_proc_count-1); cp >= child_procs; cp--) |
| 1137 | nh++; | 1153 | { |
| 1138 | active = 0; | 1154 | /* Some child_procs might be sockets; ignore them. Also |
| 1139 | goto get_result; | 1155 | ignore subprocesses whose output is not yet completely |
| 1156 | read. */ | ||
| 1157 | if (CHILD_ACTIVE (cp) | ||
| 1158 | && cp->procinfo.hProcess | ||
| 1159 | && cp->pid == pid) | ||
| 1160 | { | ||
| 1161 | our_child = 1; | ||
| 1162 | break; | ||
| 1163 | } | ||
| 1164 | } | ||
| 1165 | if (our_child) | ||
| 1166 | { | ||
| 1167 | if (cp->fd < 0 || (fd_info[cp->fd].flags & FILE_AT_EOF) != 0) | ||
| 1168 | { | ||
| 1169 | wait_hnd[nh] = cp->procinfo.hProcess; | ||
| 1170 | cps[nh] = cp; | ||
| 1171 | nh++; | ||
| 1172 | } | ||
| 1173 | else if (dont_wait) | ||
| 1174 | { | ||
| 1175 | /* PID specifies our subprocess, but its status is not | ||
| 1176 | yet available. */ | ||
| 1177 | return 0; | ||
| 1178 | } | ||
| 1179 | } | ||
| 1180 | if (nh == 0) | ||
| 1181 | { | ||
| 1182 | /* No such child process, or nothing to wait for, so fail. */ | ||
| 1183 | errno = ECHILD; | ||
| 1184 | return -1; | ||
| 1185 | } | ||
| 1140 | } | 1186 | } |
| 1141 | else | 1187 | else |
| 1142 | { | 1188 | { |
| 1143 | for (cp = child_procs + (child_proc_count-1); cp >= child_procs; cp--) | 1189 | for (cp = child_procs + (child_proc_count-1); cp >= child_procs; cp--) |
| 1144 | /* some child_procs might be sockets; ignore them */ | 1190 | { |
| 1145 | if (CHILD_ACTIVE (cp) && cp->procinfo.hProcess | 1191 | if (CHILD_ACTIVE (cp) |
| 1146 | && (cp->fd < 0 || (fd_info[cp->fd].flags & FILE_AT_EOF) != 0)) | 1192 | && cp->procinfo.hProcess |
| 1147 | { | 1193 | && (cp->fd < 0 || (fd_info[cp->fd].flags & FILE_AT_EOF) != 0)) |
| 1148 | wait_hnd[nh] = cp->procinfo.hProcess; | 1194 | { |
| 1149 | cps[nh] = cp; | 1195 | wait_hnd[nh] = cp->procinfo.hProcess; |
| 1150 | nh++; | 1196 | cps[nh] = cp; |
| 1151 | } | 1197 | nh++; |
| 1198 | } | ||
| 1199 | } | ||
| 1200 | if (nh == 0) | ||
| 1201 | { | ||
| 1202 | /* Nothing to wait on, so fail. */ | ||
| 1203 | errno = ECHILD; | ||
| 1204 | return -1; | ||
| 1205 | } | ||
| 1152 | } | 1206 | } |
| 1153 | 1207 | ||
| 1154 | if (nh == 0) | 1208 | if (dont_wait) |
| 1155 | { | 1209 | timeout_ms = 0; |
| 1156 | /* Nothing to wait on, so fail */ | 1210 | else |
| 1157 | errno = ECHILD; | 1211 | timeout_ms = 1000; /* check for quit about once a second. */ |
| 1158 | return -1; | ||
| 1159 | } | ||
| 1160 | 1212 | ||
| 1161 | do | 1213 | do |
| 1162 | { | 1214 | { |
| 1163 | /* Check for quit about once a second. */ | ||
| 1164 | QUIT; | 1215 | QUIT; |
| 1165 | active = WaitForMultipleObjects (nh, wait_hnd, FALSE, 1000); | 1216 | active = WaitForMultipleObjects (nh, wait_hnd, FALSE, timeout_ms); |
| 1166 | } while (active == WAIT_TIMEOUT); | 1217 | } while (active == WAIT_TIMEOUT); |
| 1167 | 1218 | ||
| 1168 | if (active == WAIT_FAILED) | 1219 | if (active == WAIT_FAILED) |
| @@ -1192,8 +1243,10 @@ get_result: | |||
| 1192 | } | 1243 | } |
| 1193 | if (retval == STILL_ACTIVE) | 1244 | if (retval == STILL_ACTIVE) |
| 1194 | { | 1245 | { |
| 1195 | /* Should never happen */ | 1246 | /* Should never happen. */ |
| 1196 | DebPrint (("Wait.WaitForMultipleObjects returned an active process\n")); | 1247 | DebPrint (("Wait.WaitForMultipleObjects returned an active process\n")); |
| 1248 | if (pid > 0 && dont_wait) | ||
| 1249 | return 0; | ||
| 1197 | errno = EINVAL; | 1250 | errno = EINVAL; |
| 1198 | return -1; | 1251 | return -1; |
| 1199 | } | 1252 | } |
| @@ -1207,6 +1260,8 @@ get_result: | |||
| 1207 | else | 1260 | else |
| 1208 | retval <<= 8; | 1261 | retval <<= 8; |
| 1209 | 1262 | ||
| 1263 | if (pid > 0 && active != 0) | ||
| 1264 | emacs_abort (); | ||
| 1210 | cp = cps[active]; | 1265 | cp = cps[active]; |
| 1211 | pid = cp->pid; | 1266 | pid = cp->pid; |
| 1212 | #ifdef FULL_DEBUG | 1267 | #ifdef FULL_DEBUG |
| @@ -1995,9 +2050,7 @@ count_children: | |||
| 1995 | DebPrint (("select calling SIGCHLD handler for pid %d\n", | 2050 | DebPrint (("select calling SIGCHLD handler for pid %d\n", |
| 1996 | cp->pid)); | 2051 | cp->pid)); |
| 1997 | #endif | 2052 | #endif |
| 1998 | dead_child = cp; | ||
| 1999 | sig_handlers[SIGCHLD] (SIGCHLD); | 2053 | sig_handlers[SIGCHLD] (SIGCHLD); |
| 2000 | dead_child = NULL; | ||
| 2001 | } | 2054 | } |
| 2002 | } | 2055 | } |
| 2003 | else if (fdindex[active] == -1) | 2056 | else if (fdindex[active] == -1) |