diff options
author | Ron Yorston <rmy@pobox.com> | 2016-05-18 11:06:02 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2016-05-18 11:06:02 +0100 |
commit | c7c05c8e5723ed833ed0e73d24d7f7c45169c6e9 (patch) | |
tree | eba790e9f233e0649dba0887c064970cc3bb0b2d | |
parent | 4988f3c4cc3cb9e8b1ccb06e84768c177cb13385 (diff) | |
download | busybox-w32-c7c05c8e5723ed833ed0e73d24d7f7c45169c6e9.tar.gz busybox-w32-c7c05c8e5723ed833ed0e73d24d7f7c45169c6e9.tar.bz2 busybox-w32-c7c05c8e5723ed833ed0e73d24d7f7c45169c6e9.zip |
ash: fix use of pid/handle in waitpid_child
Previously spawn was returning a process handle which was treated as a
pid in certain circumstances. This resulted in the following failing:
find . -type f | sed xargs -n 1 sed -n '1 p'
It should output the first line of each file but stopped after the
first.
-rw-r--r-- | include/mingw.h | 1 | ||||
-rw-r--r-- | shell/ash.c | 99 | ||||
-rw-r--r-- | win32/process.c | 14 |
3 files changed, 79 insertions, 35 deletions
diff --git a/include/mingw.h b/include/mingw.h index bfdf2cccd..efb17e137 100644 --- a/include/mingw.h +++ b/include/mingw.h | |||
@@ -450,6 +450,7 @@ DIR *mingw_opendir(const char *path); | |||
450 | #define PRIuMAX "I64u" | 450 | #define PRIuMAX "I64u" |
451 | 451 | ||
452 | pid_t FAST_FUNC mingw_spawn(char **argv); | 452 | pid_t FAST_FUNC mingw_spawn(char **argv); |
453 | intptr_t FAST_FUNC mingw_spawn_proc(char **argv); | ||
453 | int mingw_execv(const char *cmd, const char *const *argv); | 454 | int mingw_execv(const char *cmd, const char *const *argv); |
454 | int mingw_execvp(const char *cmd, const char *const *argv); | 455 | int mingw_execvp(const char *cmd, const char *const *argv); |
455 | int mingw_execve(const char *cmd, const char *const *argv, const char *const *envp); | 456 | int mingw_execve(const char *cmd, const char *const *argv, const char *const *envp); |
diff --git a/shell/ash.c b/shell/ash.c index 340115c35..be5f3f6e4 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -3538,6 +3538,9 @@ unaliascmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) | |||
3538 | */ | 3538 | */ |
3539 | struct procstat { | 3539 | struct procstat { |
3540 | pid_t ps_pid; /* process id */ | 3540 | pid_t ps_pid; /* process id */ |
3541 | #if ENABLE_PLATFORM_MINGW32 | ||
3542 | HANDLE ps_proc; | ||
3543 | #endif | ||
3541 | int ps_status; /* last process status from wait() */ | 3544 | int ps_status; /* last process status from wait() */ |
3542 | char *ps_cmd; /* text of command being run */ | 3545 | char *ps_cmd; /* text of command being run */ |
3543 | }; | 3546 | }; |
@@ -4159,54 +4162,69 @@ static BOOL WINAPI ctrl_handler(DWORD dwCtrlType) | |||
4159 | static pid_t | 4162 | static pid_t |
4160 | waitpid_child(int *status, int wait_flags) | 4163 | waitpid_child(int *status, int wait_flags) |
4161 | { | 4164 | { |
4162 | HANDLE *pidlist, *pidp; | 4165 | pid_t *pidlist; |
4166 | HANDLE *proclist; | ||
4163 | int pid_nr = 0; | 4167 | int pid_nr = 0; |
4164 | pid_t pid; | 4168 | pid_t pid; |
4165 | DWORD win_status, idx; | 4169 | DWORD win_status, idx; |
4166 | struct job *jb; | 4170 | struct job *jb; |
4167 | 4171 | ||
4168 | #define LOOP(stmt) \ | 4172 | for (jb = curjob; jb; jb = jb->prev_job) { |
4169 | for (jb = curjob; jb; jb = jb->prev_job) { \ | 4173 | if (jb->state != JOBDONE) |
4170 | struct procstat *ps, *psend; \ | 4174 | pid_nr += jb->nprocs; |
4171 | if (jb->state == JOBDONE) \ | 4175 | } |
4172 | continue; \ | 4176 | if ( pid_nr++ == 0 ) |
4173 | ps = jb->ps; \ | 4177 | return -1; |
4174 | psend = ps + jb->nprocs; \ | 4178 | |
4175 | while (ps < psend) { \ | 4179 | pidlist = ckmalloc(sizeof(*pidlist)*pid_nr); |
4176 | if (ps->ps_pid != -1) { \ | 4180 | proclist = ckmalloc(sizeof(*proclist)*pid_nr); |
4177 | stmt; \ | 4181 | |
4178 | } \ | 4182 | pidlist[0] = -1; |
4179 | ps++; \ | 4183 | proclist[0] = hSIGINT; |
4180 | } \ | 4184 | pid_nr = 1; |
4181 | } | 4185 | for (jb = curjob; jb; jb = jb->prev_job) { |
4182 | 4186 | struct procstat *ps, *psend; | |
4183 | LOOP(pid_nr++); | 4187 | if (jb->state == JOBDONE) |
4184 | if (!pid_nr) | 4188 | continue; |
4189 | ps = jb->ps; | ||
4190 | psend = ps + jb->nprocs; | ||
4191 | while (ps < psend) { | ||
4192 | if (ps->ps_pid != -1 && ps->ps_proc != NULL) { | ||
4193 | pidlist[pid_nr] = ps->ps_pid; | ||
4194 | proclist[pid_nr++] = ps->ps_proc; | ||
4195 | } | ||
4196 | ps++; | ||
4197 | } | ||
4198 | } | ||
4199 | |||
4200 | if (pid_nr == 1) { | ||
4201 | free(pidlist); | ||
4202 | free(proclist); | ||
4185 | return -1; | 4203 | return -1; |
4186 | pid_nr++; | 4204 | } |
4187 | pidp = pidlist = ckmalloc(sizeof(*pidlist)*pid_nr); | ||
4188 | *pidp++ = hSIGINT; | ||
4189 | LOOP(*pidp++ = (HANDLE)ps->ps_pid); | ||
4190 | #undef LOOP | ||
4191 | 4205 | ||
4192 | idx = WaitForMultipleObjects(pid_nr, pidlist, FALSE, | 4206 | idx = WaitForMultipleObjects(pid_nr, proclist, FALSE, |
4193 | wait_flags|WNOHANG ? 1 : INFINITE); | 4207 | wait_flags|WNOHANG ? 1 : INFINITE); |
4194 | if (idx >= pid_nr) { | 4208 | if (idx >= pid_nr) { |
4195 | free(pidlist); | 4209 | free(pidlist); |
4210 | free(proclist); | ||
4196 | return -1; | 4211 | return -1; |
4197 | } | 4212 | } |
4198 | if (!idx) { /* hSIGINT */ | 4213 | if (!idx) { /* hSIGINT */ |
4199 | int i; | 4214 | int i; |
4200 | ResetEvent(hSIGINT); | 4215 | ResetEvent(hSIGINT); |
4201 | for (i = 1; i < pid_nr; i++) | 4216 | for (i = 1; i < pid_nr; i++) |
4202 | TerminateProcess(pidlist[i], 1); | 4217 | TerminateProcess(proclist[i], 1); |
4218 | pid = pidlist[1]; | ||
4203 | free(pidlist); | 4219 | free(pidlist); |
4220 | free(proclist); | ||
4204 | *status = 260; /* terminated by a signal */ | 4221 | *status = 260; /* terminated by a signal */ |
4205 | return pidlist[1]; | 4222 | return pid; |
4206 | } | 4223 | } |
4207 | GetExitCodeProcess(pidlist[idx], &win_status); | 4224 | GetExitCodeProcess(proclist[idx], &win_status); |
4208 | pid = (int)pidlist[idx]; | 4225 | pid = pidlist[idx]; |
4209 | free(pidlist); | 4226 | free(pidlist); |
4227 | free(proclist); | ||
4210 | *status = (int)win_status; | 4228 | *status = (int)win_status; |
4211 | return pid; | 4229 | return pid; |
4212 | } | 4230 | } |
@@ -4255,8 +4273,11 @@ dowait(int wait_flags, struct job *job) | |||
4255 | jobno(jp), pid, ps->ps_status, status)); | 4273 | jobno(jp), pid, ps->ps_status, status)); |
4256 | ps->ps_status = status; | 4274 | ps->ps_status = status; |
4257 | thisjob = jp; | 4275 | thisjob = jp; |
4258 | if (ENABLE_PLATFORM_MINGW32) | 4276 | if (ENABLE_PLATFORM_MINGW32) { |
4259 | ps->ps_pid = -1; | 4277 | ps->ps_pid = -1; |
4278 | CloseHandle(ps->ps_proc); | ||
4279 | ps->ps_proc = NULL; | ||
4280 | } | ||
4260 | } | 4281 | } |
4261 | if (ps->ps_status == -1) | 4282 | if (ps->ps_status == -1) |
4262 | jobstate = JOBRUNNING; | 4283 | jobstate = JOBRUNNING; |
@@ -5096,8 +5117,15 @@ forkchild(struct job *jp, union node *n, int mode) | |||
5096 | #define forkparent(jp, n, mode, pid) forkparent(jp, mode, pid) | 5117 | #define forkparent(jp, n, mode, pid) forkparent(jp, mode, pid) |
5097 | #endif | 5118 | #endif |
5098 | static void | 5119 | static void |
5120 | #if !ENABLE_PLATFORM_MINGW32 | ||
5099 | forkparent(struct job *jp, union node *n, int mode, pid_t pid) | 5121 | forkparent(struct job *jp, union node *n, int mode, pid_t pid) |
5122 | #else | ||
5123 | forkparent(struct job *jp, union node *n, int mode, HANDLE proc) | ||
5124 | #endif | ||
5100 | { | 5125 | { |
5126 | #if ENABLE_PLATFORM_MINGW32 | ||
5127 | pid_t pid = GetProcessId(proc); | ||
5128 | #endif | ||
5101 | TRACE(("In parent shell: child = %d\n", pid)); | 5129 | TRACE(("In parent shell: child = %d\n", pid)); |
5102 | if (!jp && !ENABLE_PLATFORM_MINGW32) { /* FIXME not quite understand this */ | 5130 | if (!jp && !ENABLE_PLATFORM_MINGW32) { /* FIXME not quite understand this */ |
5103 | while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0) | 5131 | while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0) |
@@ -5124,6 +5152,9 @@ forkparent(struct job *jp, union node *n, int mode, pid_t pid) | |||
5124 | if (jp) { | 5152 | if (jp) { |
5125 | struct procstat *ps = &jp->ps[jp->nprocs++]; | 5153 | struct procstat *ps = &jp->ps[jp->nprocs++]; |
5126 | ps->ps_pid = pid; | 5154 | ps->ps_pid = pid; |
5155 | #if ENABLE_PLATFORM_MINGW32 | ||
5156 | ps->ps_proc = proc; | ||
5157 | #endif | ||
5127 | ps->ps_status = -1; | 5158 | ps->ps_status = -1; |
5128 | ps->ps_cmd = nullstr; | 5159 | ps->ps_cmd = nullstr; |
5129 | #if JOBS | 5160 | #if JOBS |
@@ -14000,20 +14031,20 @@ spawn_forkshell(struct job *jp, struct forkshell *fs, int mode) | |||
14000 | struct forkshell *new; | 14031 | struct forkshell *new; |
14001 | char buf[16]; | 14032 | char buf[16]; |
14002 | const char *argv[] = { "sh", "--forkshell", NULL, NULL }; | 14033 | const char *argv[] = { "sh", "--forkshell", NULL, NULL }; |
14003 | pid_t pid; | 14034 | intptr_t ret; |
14004 | 14035 | ||
14005 | new = forkshell_prepare(fs); | 14036 | new = forkshell_prepare(fs); |
14006 | sprintf(buf, "%x", (unsigned int)new->hMapFile); | 14037 | sprintf(buf, "%x", (unsigned int)new->hMapFile); |
14007 | argv[2] = buf; | 14038 | argv[2] = buf; |
14008 | pid = spawn(argv); | 14039 | ret = mingw_spawn_proc(argv); |
14009 | CloseHandle(new->hMapFile); | 14040 | CloseHandle(new->hMapFile); |
14010 | UnmapViewOfFile(new); | 14041 | UnmapViewOfFile(new); |
14011 | if (pid == -1) { | 14042 | if (ret == -1) { |
14012 | free(jp); | 14043 | free(jp); |
14013 | return -1; | 14044 | return -1; |
14014 | } | 14045 | } |
14015 | forkparent(jp, fs->node, mode, pid); | 14046 | forkparent(jp, fs->node, mode, (HANDLE)ret); |
14016 | return pid; | 14047 | return ret == -1 ? -1 : 0; |
14017 | } | 14048 | } |
14018 | 14049 | ||
14019 | /* | 14050 | /* |
diff --git a/win32/process.c b/win32/process.c index 8cd1dc28c..9a4b05597 100644 --- a/win32/process.c +++ b/win32/process.c | |||
@@ -332,7 +332,19 @@ mingw_spawn_1(int mode, const char *cmd, const char *const *argv, const char *co | |||
332 | pid_t FAST_FUNC | 332 | pid_t FAST_FUNC |
333 | mingw_spawn(char **argv) | 333 | mingw_spawn(char **argv) |
334 | { | 334 | { |
335 | return mingw_spawn_1(P_NOWAIT, argv[0], (const char *const *)argv, (const char *const *)environ); | 335 | intptr_t ret; |
336 | |||
337 | ret = mingw_spawn_1(P_NOWAIT, argv[0], (const char *const *)argv, | ||
338 | (const char *const *)environ); | ||
339 | |||
340 | return ret == -1 ? -1 : GetProcessId((HANDLE)ret); | ||
341 | } | ||
342 | |||
343 | intptr_t FAST_FUNC | ||
344 | mingw_spawn_proc(char **argv) | ||
345 | { | ||
346 | return mingw_spawn_1(P_NOWAIT, argv[0], (const char *const *)argv, | ||
347 | (const char *const *)environ); | ||
336 | } | 348 | } |
337 | 349 | ||
338 | int | 350 | int |