From da9ffe378fd00bc0853aefdda7ee70401dcf3994 Mon Sep 17 00:00:00 2001 From: nobu Date: Sun, 1 Mar 2009 07:15:33 +0000 Subject: [PATCH] * process.c (rb_waitpid): use wait_each() on no waitpid platforms. [ruby-dev:38054] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@22688 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 5 ++++ process.c | 78 +++++++++++++++++++++++++++++++------------------------ 2 files changed, 49 insertions(+), 34 deletions(-) diff --git a/ChangeLog b/ChangeLog index 49f1eea25a..1f838442b7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Sun Mar 1 16:15:31 2009 Nobuyoshi Nakada + + * process.c (rb_waitpid): use wait_each() on no waitpid platforms. + [ruby-dev:38054] + Sun Mar 1 16:01:01 2009 Nobuyoshi Nakada * process.c (proc_daemon): stops and restarts timer thread because diff --git a/process.c b/process.c index c8192a8e77..fb18d96001 100644 --- a/process.c +++ b/process.c @@ -590,6 +590,29 @@ pst_wcoredump(VALUE st) #if !defined(HAVE_WAITPID) && !defined(HAVE_WAIT4) #define NO_WAITPID static st_table *pid_tbl; + +struct wait_data { + rb_pid_t pid; + int status; +}; + +static int +wait_each(rb_pid_t pid, int status, struct wait_data *data) +{ + if (data->status != -1) return ST_STOP; + + data->pid = pid; + data->status = status; + return ST_DELETE; +} + +static int +waitall_each(rb_pid_t pid, int status, VALUE ary) +{ + rb_last_status_set(status, pid); + rb_ary_push(ary, rb_assoc_new(PIDT2NUM(pid), rb_last_status_get())); + return ST_DELETE; +} #else struct waitpid_arg { rb_pid_t pid; @@ -624,7 +647,7 @@ rb_waitpid(rb_pid_t pid, int *st, int flags) #ifndef NO_WAITPID struct waitpid_arg arg; -retry: + retry: arg.pid = pid; arg.st = st; arg.flags = flags; @@ -635,13 +658,25 @@ retry: RUBY_VM_CHECK_INTS(); goto retry; } - return -1; + return (rb_pid_t)-1; } #else /* NO_WAITPID */ - if (pid_tbl && st_lookup(pid_tbl, pid, (st_data_t *)st)) { - rb_last_status_set(*st, pid); - st_delete(pid_tbl, (st_data_t*)&pid, NULL); - return pid; + if (pid_tbl) { + st_data_t status, piddata = (st_data_t)pid; + if (pid == (rb_pid_t)-1) { + struct wait_data data; + data.pid = (rb_pid_t)-1; + data.status = -1; + st_foreach(pid_tbl, wait_each, (st_data_t)&data); + if (data.status != -1) { + rb_last_status_set(data.status, data.pid); + return data.pid; + } + } + else if (st_delete(pid_tbl, &piddata, &status)) { + rb_last_status_set(*st = (int)status, pid); + return pid; + } } if (flags) { @@ -656,13 +691,13 @@ retry: rb_thread_schedule(); continue; } - return -1; + return (rb_pid_t)-1; } - if (result == pid) { + if (result == pid || pid == (rb_pid_t)-1) { break; } if (!pid_tbl) - pid_tbl = st_init_numtable(); + pid_tbl = st_init_numtable(); st_insert(pid_tbl, pid, (st_data_t)st); if (!rb_thread_alone()) rb_thread_schedule(); } @@ -673,31 +708,6 @@ retry: return result; } -#ifdef NO_WAITPID -struct wait_data { - rb_pid_t pid; - int status; -}; - -static int -wait_each(rb_pid_t pid, int status, struct wait_data *data) -{ - if (data->status != -1) return ST_STOP; - - data->pid = pid; - data->status = status; - return ST_DELETE; -} - -static int -waitall_each(rb_pid_t pid, int status, VALUE ary) -{ - rb_last_status_set(status, pid); - rb_ary_push(ary, rb_assoc_new(PIDT2NUM(pid), rb_last_status_get())); - return ST_DELETE; -} -#endif - /* [MG]:FIXME: I wasn't sure how this should be done, since ::wait() has historically been documented as if it didn't take any arguments