From fac6d9a6d59a83e96314103b3181f6f692537014 Mon Sep 17 00:00:00 2001 From: "Michael I. Bushnell" Date: Thu, 25 Apr 1996 19:36:50 +0000 Subject: Many changes to support multi-threading. See ChangeLog. --- proc/Makefile | 15 ++++--- proc/host.c | 24 ++++++++++- proc/info.c | 49 ++++++++++++++++++++-- proc/main.c | 62 ++++++++++++++-------------- proc/msg.c | 43 +++++++++++++------- proc/notify.c | 22 +++++----- proc/pgrp.c | 24 ++++++++++- proc/proc.h | 34 +++++++++------- proc/wait.c | 127 ++++++++++++++++++++-------------------------------------- 9 files changed, 233 insertions(+), 167 deletions(-) diff --git a/proc/Makefile b/proc/Makefile index e162918d..b666c4f7 100644 --- a/proc/Makefile +++ b/proc/Makefile @@ -24,13 +24,18 @@ SRCS = wait.c hash.c host.c info.c main.c mgt.c notify.c pgrp.c msg.c \ LCLHDRS = proc.h DIST_FILES = proc_exc.defs ourmsg.defs -MIGSTUBS = processServer.o notifyServer.o process_replyUser.o \ +MIGSFLAGS="-DPROCESS_INTRAN=pstruct_t reqport_find (process_t)" \ + "-DPROCESS_DESTRUCTOR=process_drop (pstruct_t)" \ + "-DPROCESS_IMPORTS=import \"proc.h\";" + +MIGSTUBS = processServer.o notifyServer.o \ ourmsgUser.o proc_excUser.o proc_excServer.o OBJS = $(SRCS:.c=.o) $(MIGSTUBS) -MIGSFLAGS ="-DPROCESS_INTRAN=pstruct_t reqport_find (process_t)" \ - "-DPROCESS_IMPORTS=import \"proc.h\";" - -proc: $(OBJS) ../libthreads/libthreads.a ../libihash/libihash.a +proc: $(OBJS) ../libthreads/libthreads.a ../libihash/libihash.a \ + ../libports/libports.a ../libshouldbeinlibc/libshouldbeinlibc.a include ../Makeconf + +mutated_ourmsg_U.h: ourmsg_U.h + sed -e 's/_msg_user_/_ourmsg_user_/' < $< > $@ diff --git a/proc/host.c b/proc/host.c index afa8159e..3b1e03c8 100644 --- a/proc/host.c +++ b/proc/host.c @@ -1,5 +1,5 @@ /* Proc server host management calls - Copyright (C) 1992, 1993, 1994 Free Software Foundation + Copyright (C) 1992, 1993, 1994, 1996 Free Software Foundation This file is part of the GNU Hurd. @@ -62,6 +62,9 @@ kern_return_t S_proc_sethostid (struct proc *p, int newhostid) { + if (!p) + return EOPNOTSUPP; + if (! check_uid (p, 0)) return EPERM; @@ -75,6 +78,7 @@ kern_return_t S_proc_gethostid (struct proc *p, int *outhostid) { + /* No need to check P here; we don't use it. */ *outhostid = hostid; return 0; } @@ -86,6 +90,9 @@ S_proc_sethostname (struct proc *p, u_int newhostnamelen) { int len; + if (!p) + return EOPNOTSUPP; + if (! check_uid (p, 0)) return EPERM; @@ -113,6 +120,8 @@ S_proc_gethostname (struct proc *p, char **outhostname, u_int *outhostnamelen) { + /* No need to check P here; we don't use it. */ + if (*outhostnamelen < hostnamelen + 1) vm_allocate (mach_task_self (), (vm_address_t *)outhostname, hostnamelen + 1, 1); @@ -130,6 +139,9 @@ S_proc_getprivports (struct proc *p, mach_port_t *hostpriv, mach_port_t *devpriv) { + if (!p) + return EOPNOTSUPP; + if (! check_uid (p, 0)) return EPERM; @@ -150,6 +162,9 @@ S_proc_setexecdata (struct proc *p, int i; struct execdata_notify *n; + if (!p) + return EOPNOTSUPP; + if (!check_uid (p, 0)) return EPERM; @@ -186,6 +201,8 @@ S_proc_getexecdata (struct proc *p, int **ints, u_int *nints) { + /* No need to check P here; we don't use it. */ + /* XXX memory leak here */ if (!std_port_array) @@ -212,6 +229,8 @@ S_proc_execdata_notify (struct proc *p, struct execdata_notify *n = malloc (sizeof (struct execdata_notify)); mach_port_t foo; + /* No need to check P here; we don't use it. */ + n->notify_port = notify; n->next = execdata_notifys; execdata_notifys = n; @@ -427,6 +446,7 @@ kern_return_t S_proc_uname (pstruct_t process, struct utsname *uname) { + /* No need to check PROCESS here, we don't use it. */ *uname = uname_info; return 0; } @@ -440,6 +460,8 @@ S_proc_register_version (pstruct_t server, { int i; + /* No need to check SERVER here; we don't use it. */ + if (credential != master_host_port) /* Must be privileged to register for uname. */ return EPERM; diff --git a/proc/info.c b/proc/info.c index b0b2feff..936345b9 100644 --- a/proc/info.c +++ b/proc/info.c @@ -38,11 +38,20 @@ S_proc_pid2task (struct proc *callerp, pid_t pid, task_t *t) { - struct proc *p = pid_find (pid); + struct proc *p = pid_find_allow_zombie (pid); + + if (!callerp) + return EOPNOTSUPP; if (!p) return ESRCH; + if (p->p_dead) + { + *t = MACH_PORT_NULL; + return 0; + } + if (!check_uid (callerp, p->p_owner)) return EPERM; *t = p->p_task; @@ -58,6 +67,8 @@ S_proc_task2pid (struct proc *callerp, { struct proc *p = task_find (t); + /* No need to check CALLERP here; we don't use it. */ + if (!p) return ESRCH; @@ -74,10 +85,12 @@ S_proc_task2proc (struct proc *callerp, { struct proc *p = task_find (t); + /* No need to check CALLERP here; we don't use it. */ + if (!p) return ESRCH; - *outproc = p->p_reqport; + *outproc = ports_get_right (p); mach_port_deallocate (mach_task_self (), t); return 0; } @@ -87,6 +100,8 @@ kern_return_t S_proc_proc2task (struct proc *p, task_t *t) { + if (!p) + return EOPNOTSUPP; *t = p->p_task; return 0; } @@ -97,15 +112,24 @@ S_proc_pid2proc (struct proc *callerp, pid_t pid, mach_port_t *outproc) { - struct proc *p = pid_find (pid); + struct proc *p = pid_find_allow_zombie (pid); + + if (!callerp) + return EOPNOTSUPP; if (!p) return ESRCH; + if (p->p_dead) + { + *outproc = MACH_PORT_NULL; + return 0; + } + if (!check_uid (callerp, p->p_owner)) return EPERM; - *outproc = p->p_reqport; + *outproc = ports_get_right (p); return 0; } @@ -289,6 +313,8 @@ S_proc_getprocargs (struct proc *callerp, { struct proc *p = pid_find (pid); + /* No need to check CALLERP here; we don't use it. */ + if (!p) return ESRCH; @@ -304,6 +330,8 @@ S_proc_getprocenv (struct proc *callerp, { struct proc *p = pid_find (pid); + /* No need to check CALLERP here; we don't use it. */ + if (!p) return ESRCH; @@ -332,6 +360,8 @@ S_proc_getprocinfo (struct proc *callerp, u_int tkcount, thcount; struct proc *tp; + /* No need to check CALLERP here; we don't use it. */ + if (!p) return ESRCH; @@ -508,6 +538,8 @@ S_proc_getprocinfo (struct proc *callerp, kern_return_t S_proc_make_login_coll (struct proc *p) { + if (!p) + return EOPNOTSUPP; p->p_loginleader = 1; return 0; } @@ -521,6 +553,8 @@ S_proc_getloginid (struct proc *callerp, struct proc *proc = pid_find (pid); struct proc *p; + /* No need to check CALLERP here; we don't use it. */ + if (!proc) return ESRCH; @@ -544,6 +578,8 @@ S_proc_getloginpids (struct proc *callerp, int parraysize; int i; + /* No need to check CALLERP here; we don't use it. */ + if (!l || !l->p_loginleader) return ESRCH; @@ -587,6 +623,9 @@ S_proc_setlogin (struct proc *p, { struct login *l; + if (!p) + return EOPNOTSUPP; + if (!check_uid (p, 0)) return EPERM; @@ -604,6 +643,8 @@ kern_return_t S_proc_getlogin (struct proc *p, char *login) { + if (!p) + return EOPNOTSUPP; strcpy (login, p->p_login->l_name); return 0; } diff --git a/proc/main.c b/proc/main.c index 1bba468d..40a0379c 100644 --- a/proc/main.c +++ b/proc/main.c @@ -24,11 +24,10 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include +#include #include "proc.h" - - int message_demuxer (mach_msg_header_t *inp, mach_msg_header_t *outp) @@ -36,10 +35,15 @@ message_demuxer (mach_msg_header_t *inp, extern int process_server (mach_msg_header_t *, mach_msg_header_t *); extern int notify_server (mach_msg_header_t *, mach_msg_header_t *); extern int proc_exc_server (mach_msg_header_t *, mach_msg_header_t *); - - return (process_server (inp, outp) - || notify_server (inp, outp) - || proc_exc_server (inp, outp)); + int status; + + mutex_lock (&global_lock); + status = (process_server (inp, outp) + || notify_server (inp, outp) + || ports_interrupt_server (inp, outp) + || proc_exc_server (inp, outp)); + mutex_unlock (&global_lock); + return status; } struct mutex global_lock = MUTEX_INITIALIZER; @@ -50,28 +54,36 @@ main (int argc, char **argv, char **envp) mach_port_t boot; error_t err; mach_port_t pset, psetcntl; + void *genport; + process_t startup_port; + volatile int hold = 0; + + while (hold); + initialize_version_info (); task_get_bootstrap_port (mach_task_self (), &boot); - mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_PORT_SET, - &request_portset); - - mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE, - &generic_port); - mach_port_move_member (mach_task_self (), generic_port, request_portset); + proc_bucket = ports_create_bucket (); + proc_class = ports_create_class (0, 0); + generic_port_class = ports_create_class (0, 0); + exc_class = ports_create_class (exc_clean, 0); + ports_create_port (generic_port_class, proc_bucket, + sizeof (struct port_info), &genport); + generic_port = ports_get_right (genport); /* new_proc depends on these assignments which must occur in this order. */ self_proc = new_proc (mach_task_self ()); /* proc 0 is the procserver */ startup_proc = new_proc (MACH_PORT_NULL); /* proc 1 is init */ - mach_port_insert_right (mach_task_self (), startup_proc->p_reqport, - startup_proc->p_reqport, MACH_MSG_TYPE_MAKE_SEND); - err = startup_procinit (boot, startup_proc->p_reqport, &startup_proc->p_task, + startup_port = ports_get_right (startup_proc); + mach_port_insert_right (mach_task_self (), startup_port, + startup_port, MACH_MSG_TYPE_MAKE_SEND); + err = startup_procinit (boot, startup_port, &startup_proc->p_task, &authserver, &master_host_port, &master_device_port); assert (!err); - mach_port_deallocate (mach_task_self (), startup_proc->p_reqport); + mach_port_deallocate (mach_task_self (), startup_port); mach_port_mod_refs (mach_task_self (), authserver, MACH_PORT_RIGHT_SEND, 1); _hurd_port_set (&_hurd_ports[INIT_PORT_AUTH], authserver); @@ -98,20 +110,10 @@ main (int argc, char **argv, char **envp) mach_port_deallocate (mach_task_self (), pset); mach_port_deallocate (mach_task_self (), psetcntl); - { - extern void _start (); - extern char _edata, _etext, __data_start; - vm_address_t text_start = (vm_address_t) &_start; - err = vm_wire (master_host_port, mach_task_self (), - (vm_address_t) text_start, - (vm_size_t) (&_etext - text_start), - VM_PROT_READ|VM_PROT_EXECUTE); - err = vm_wire (master_host_port, mach_task_self (), - (vm_address_t) &__data_start, - (vm_size_t) (&_edata - &__data_start), - VM_PROT_READ|VM_PROT_WRITE); - } + wire_task_self (); while (1) - mach_msg_server (message_demuxer, 0, request_portset); + ports_manage_port_operations_multithread (proc_bucket, + message_demuxer, + 0, 0, 0, 0); } diff --git a/proc/msg.c b/proc/msg.c index fe78a895..b1abdaac 100644 --- a/proc/msg.c +++ b/proc/msg.c @@ -18,7 +18,6 @@ #include #include #include "proc.h" -#include "process_reply_U.h" #include #include #include @@ -35,12 +34,24 @@ check_message_return (struct proc *p, void *availpaddr) } } +/* Register ourselves with init. */ +static any_t +tickle_init (any_t initport) +{ + startup_essential_task ((mach_port_t) initport, mach_task_self (), + MACH_PORT_NULL, "proc", master_host_port); + return 0; +} + error_t S_proc_setmsgport (struct proc *p, mach_port_t reply, mach_msg_type_name_t replytype, mach_port_t msgport, mach_port_t *oldmsgport) { + if (!p) + return EOPNOTSUPP; + *oldmsgport = p->p_msgport; p->p_msgport = msgport; p->p_deadmsg = 0; @@ -49,21 +60,15 @@ S_proc_setmsgport (struct proc *p, p->p_checkmsghangs = 0; if (p == startup_proc) - { - /* init is single-threaded. Reply to it before we expect it - to service requests. */ - proc_setmsgport_reply (reply, replytype, 0, *oldmsgport); - mach_port_deallocate (mach_task_self (), *oldmsgport); - startup_essential_task (msgport, mach_task_self (), MACH_PORT_NULL, - "proc", master_host_port); - return MIG_NO_REPLY; - } - else - return 0; + /* Init is single threaded, so we can't delay our reply for + the essential task RPC; spawn a thread to do it. */ + cthread_detach (cthread_fork (tickle_init, (any_t) msgport)); + + return 0; } /* Check to see if process P is blocked trying to get the message port of - process DYINGP; if so, return its call with ESRCH. */ + process DYINGP; if so, wake it up. */ void check_message_dying (struct proc *p, struct proc *dyingp) { @@ -81,7 +86,11 @@ S_proc_getmsgport (struct proc *callerp, pid_t pid, mach_port_t *msgport) { - struct proc *p = pid_find (pid); + struct proc *p = pid_find_allow_zombie (pid); + int cancel; + + if (!callerp) + return EOPNOTSUPP; if (!p) return ESRCH; @@ -90,7 +99,11 @@ S_proc_getmsgport (struct proc *callerp, { callerp->p_msgportwait = 1; p->p_checkmsghangs = 1; - condition_wait (&callerp->p_wakeup, &global_lock); + cancel = hurd_condition_wait (&callerp->p_wakeup, &global_lock); + if (callerp->p_dead) + return EOPNOTSUPP; + if (cancel) + return EINTR; } *msgport = p->p_msgport; diff --git a/proc/notify.c b/proc/notify.c index 19a8be33..9d48d945 100644 --- a/proc/notify.c +++ b/proc/notify.c @@ -47,23 +47,28 @@ do_mach_notify_dead_name (mach_port_t notify, return 0; } - p = reqport_find (notify); + p = ports_lookup_port (proc_bucket, notify, proc_class); if (!p) return EOPNOTSUPP; - if (p->p_reqport == deadport) + if (p->p_msgport == deadport) { message_port_dead (p); + ports_port_deref (p); return 0; } else if (p->p_task == deadport) { process_has_exited (p); + ports_port_deref (p); return 0; } else - return EINVAL; + { + ports_port_deref (p); + return EINVAL; + } } /* We get no-senders notifications on exception ports that we @@ -72,16 +77,7 @@ kern_return_t do_mach_notify_no_senders (mach_port_t notify, mach_port_mscount_t mscount) { - struct exc *e = exc_find (notify); - if (!e) - return EOPNOTSUPP; - - remove_exc_from_hash (e); - mach_port_mod_refs (mach_task_self (), e->excport, - MACH_PORT_RIGHT_RECEIVE, -1); - mach_port_deallocate (mach_task_self (), e->forwardport); - free (e); - return 0; + return ports_do_mach_notify_no_senders (notify, mscount); } kern_return_t diff --git a/proc/pgrp.c b/proc/pgrp.c index 219274af..3ff8ca1a 100644 --- a/proc/pgrp.c +++ b/proc/pgrp.c @@ -28,7 +28,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "proc.h" #include "process_S.h" -#include "ourmsg_U.h" +#include "mutated_ourmsg_U.h" /* Create and return a new process group with pgid PGID in session SESS. */ @@ -100,6 +100,9 @@ S_proc_setsid (struct proc *p) { struct session *sess; + if (!p) + return EOPNOTSUPP; + if (p->p_pgrp->pg_pgid == p->p_pid || pgrp_find (p->p_pid)) return EPERM; @@ -134,6 +137,8 @@ S_proc_getsid (struct proc *callerp, if (!p) return ESRCH; + /* No need to check CALLERP; we don't use it. */ + *sid = p->p_pgrp->pg_session->s_sid; return 0; } @@ -152,6 +157,8 @@ S_proc_getsessionpids (struct proc *callerp, pid_t *pp = *pids; u_int npids = *npidsp; + /* No need to check CALLERP; we don't use it. */ + s = session_find (sid); if (!s) return ESRCH; @@ -193,6 +200,8 @@ S_proc_getsessionpgids (struct proc *callerp, pid_t *pp = *pgids; int npgids = *npgidsp; + /* No need to check CALLERP; we don't use it. */ + s = session_find (sid); if (!s) return ESRCH; @@ -229,6 +238,8 @@ S_proc_getpgrppids (struct proc *callerp, pid_t *pp = *pids; unsigned int npids = *npidsp, count; + /* No need to check CALLERP; we don't use it. */ + if (pgid == 0) pg = callerp->p_pgrp; else @@ -263,6 +274,10 @@ S_proc_getsidport (struct proc *p, mach_port_t *sessport, mach_msg_type_name_t *sessport_type) { error_t err = 0; + + if (!p) + return EOPNOTSUPP; + if (!p->p_pgrp) *sessport = MACH_PORT_NULL; else @@ -285,6 +300,9 @@ S_proc_setpgrp (struct proc *callerp, struct proc *p; struct pgrp *pg; + if (!callerp) + return EOPNOTSUPP; + p = pid ? pid_find (pid) : callerp; if (!p || (p != callerp && p->p_parent != callerp)) @@ -323,6 +341,8 @@ S_proc_getpgrp (struct proc *callerp, pid_t *pgid) { struct proc *p = pid_find (pid); + + /* No need to check CALLERP; we don't use it. */ if (!p) return ESRCH; @@ -337,6 +357,8 @@ S_proc_getpgrp (struct proc *callerp, kern_return_t S_proc_mark_exec (struct proc *p) { + if (!p) + return EOPNOTSUPP; p->p_exec = 1; return 0; } diff --git a/proc/proc.h b/proc/proc.h index ee5a8d10..1991a6d8 100644 --- a/proc/proc.h +++ b/proc/proc.h @@ -23,10 +23,12 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #define PROC_H_INCLUDED #include +#include +#include struct proc { - mach_port_t p_reqport; + struct port_info p_pi; /* List of members of a process group */ struct proc *p_gnext, **p_gprevp; /* process group */ @@ -34,7 +36,6 @@ struct proc /* Hash table pointers that point here */ void **p_pidhashloc; /* by pid */ void **p_taskhashloc; /* by task port */ - void **p_porthashloc; /* by request port */ /* Identification of this process */ task_t p_task; @@ -76,6 +77,7 @@ struct proc int p_msgportwait:1; /* blocked in getmsgport */ int p_noowner:1; /* has no owner known */ int p_loginleader:1; /* leader of login collection */ + int p_dead:1; /* process is dead */ }; typedef struct proc *pstruct_t; @@ -115,30 +117,23 @@ struct ids /* Structure for an exception port we are listening on. */ struct exc { - mach_port_t excport; /* Receive right. */ + struct port_info pi; mach_port_t forwardport; /* Send right to forward msg to. */ - void **hashloc; int flavor; /* State to restore faulting thread to. */ mach_msg_type_number_t statecnt; natural_t thread_state[0]; }; -struct zombie -{ - struct zombie *next; - pid_t pid, pgrp; - struct proc *parent; - int exit_status; - struct rusage ru; -}; - struct zombie *zombie_list; mach_port_t authserver; struct proc *self_proc; /* process 0 (us) */ struct proc *startup_proc; /* process 1 (init) */ -mach_port_t request_portset; +struct port_bucket *proc_bucket; +struct port_class *proc_class; +struct port_class *generic_port_class; +struct port_class *exc_class; mach_port_t master_host_port; mach_port_t master_device_port; @@ -151,6 +146,13 @@ struct mutex global_lock; #define OUR_SERVER_NAME "proc" #define OUR_VERSION "0.0 pre-alpha" +extern inline void +process_drop (struct proc *p) +{ + if (p) + ports_port_deref (p); +} + /* Forward declarations */ void complete_wait (struct proc *, int); int nextprime (int); @@ -179,12 +181,15 @@ void remove_pgrp_from_hash (struct pgrp *); void remove_exc_from_hash (struct exc *); struct exc *exc_find (mach_port_t); struct proc *pid_find (int); +struct proc *pid_find_allow_zombie (int); struct proc *task_find (task_t); struct proc *task_find_nocreate (task_t); struct pgrp *pgrp_find (int); struct proc *reqport_find (mach_port_t); struct session *session_find (pid_t); +void exc_clean (void *); + struct proc *add_tasks (task_t); int pidfree (pid_t); @@ -197,6 +202,7 @@ void boot_setsid (struct proc *); void process_has_exited (struct proc *); void alert_parent (struct proc *); void reparent_zombies (struct proc *); +void complete_exit (struct proc *); void initialize_version_info (void); diff --git a/proc/wait.c b/proc/wait.c index 57fc4cad..6c862887 100644 --- a/proc/wait.c +++ b/proc/wait.c @@ -30,9 +30,6 @@ #include #include "process_S.h" -#include "process_reply_U.h" -#include "ourmsg_U.h" - #include /* Return nonzero if a `waitpid' on WAIT_PID by a process @@ -47,14 +44,11 @@ waiter_cares (pid_t wait_pid, pid_t mypgrp, (wait_pid == WAIT_MYPGRP && pgrp == mypgrp)); } -/* A process is dying. Send SIGCHLD to the parent. Check if the parent is - waiting for us to exit; if so wake it up, otherwise, enter us as a - zombie. */ +/* A process is dying. Send SIGCHLD to the parent. Wake the parent +if it is waiting for us to exit. */ void alert_parent (struct proc *p) { - struct zombie *z; - send_signal (p->p_parent->p_msgport, SIGCHLD, p->p_parent->p_task); if (!p->p_exiting) @@ -65,50 +59,8 @@ alert_parent (struct proc *p) condition_broadcast (&p->p_parent->p_wakeup); p->p_parent->p_waiting = 0; } - - z = malloc (sizeof (struct zombie)); - - z->pid = p->p_pid; - z->pgrp = p->p_pgrp->pg_pgid; - z->parent = p->p_parent; - z->exit_status = p->p_status; - bzero (&z->ru, sizeof (struct rusage)); - z->next = zombie_list; - zombie_list = z; -} - -/* Process P is exiting. Find all the zombies who claim P as their parent - and make them claim startup_proc as their parent; then wake it - up if appropriate. */ -void -reparent_zombies (struct proc *p) -{ - struct zombie *z, *prevz; - struct wait_c *w = &startup_proc->p_continuation.wait_c; - int initsignalled = 0; - - for (z = zombie_list, prevz = 0; z; prevz = z, z = z->next) - { - if (z->parent != p) - continue; - z->parent = startup_proc; - - if (!initsignalled) - { - send_signal (startup_proc->p_msgport, SIGCHLD, startup_proc->p_task); - initsignalled = 1; - } - - if (startup_proc->p_waiting) - { - condition_broadcast (&startup_proc->p_wakeup); - startup_proc->p_waiting = 0; - } - } } - -/* Implement proc_wait as described in . */ kern_return_t S_proc_wait (struct proc *p, mach_port_t reply_port, @@ -119,24 +71,25 @@ S_proc_wait (struct proc *p, struct rusage *ru, pid_t *pid_status) { - struct wait_c *w; - struct zombie *z, *prevz; + int cancel; - start_over: - for (z = zombie_list, prevz = 0; z; prevz = z, z = z->next) + int child_ready (struct proc *child) { - if (z->parent == p && waiter_cares (pid, p->p_pgrp->pg_pgid, - z->pid, z->pgrp)) - { - *status = z->exit_status; - bzero (ru, sizeof (struct rusage)); - *pid_status = z->pid; - (prevz ? prevz->next : zombie_list) = z->next; - free (z); - return 0; - } + if (child->p_waited) + return 0; + if (child->p_dead) + return 1; + if (!child->p_stopped) + return 0; + if (child->p_traced || (options & WUNTRACED)) + return 1; + return 0; } + if (!p) + return EOPNOTSUPP; + + start_over: /* See if we can satisfy the request with a stopped child; also check for invalid arguments here. */ if (!p->p_ochild) @@ -144,14 +97,15 @@ S_proc_wait (struct proc *p, if (pid > 0) { - struct proc *child = pid_find (pid); + struct proc *child = pid_find_allow_zombie (pid); if (!child || child->p_parent != p) return ECHILD; - if (child->p_stopped && !child->p_waited - && ((options & WUNTRACED) || child->p_traced)) + if (child_ready (child)) { child->p_waited = 1; *status = child->p_status; + if (child->p_dead) + complete_exit (child); bzero (ru, sizeof (struct rusage)); *pid_status = pid; return 0; @@ -161,19 +115,20 @@ S_proc_wait (struct proc *p, { struct proc *child; int had_a_match = pid == 0; - + for (child = p->p_ochild; child; child = child->p_sib) if (waiter_cares (pid, p->p_pgrp->pg_pgid, child->p_pid, child->p_pgrp->pg_pgid)) { had_a_match = 1; - if (child->p_stopped && !child->p_waited - && ((options & WUNTRACED) || child->p_traced)) + if (child_ready (child)) { child->p_waited = 1; *status = child->p_status; - bzero (ru, sizeof (struct rusage)); *pid_status = child->p_pid; + if (child->p_dead) + complete_exit (child); + bzero (ru, sizeof (struct rusage)); return 0; } } @@ -186,7 +141,11 @@ S_proc_wait (struct proc *p, return EWOULDBLOCK; p->p_waiting = 1; - condition_wait (&p->p_wakeup, &global_lock); + cancel = hurd_condition_wait (&p->p_wakeup, &global_lock); + if (p->p_dead) + return EOPNOTSUPP; + if (cancel) + return EINTR; goto start_over; } @@ -195,6 +154,9 @@ kern_return_t S_proc_mark_stop (struct proc *p, int signo) { + if (!p) + return EOPNOTSUPP; + p->p_stopped = 1; p->p_status = W_STOPCODE (signo); p->p_waited = 0; @@ -216,6 +178,9 @@ kern_return_t S_proc_mark_exit (struct proc *p, int status) { + if (!p) + return EOPNOTSUPP; + if (WIFSTOPPED (status)) return EINVAL; @@ -228,6 +193,8 @@ S_proc_mark_exit (struct proc *p, kern_return_t S_proc_mark_cont (struct proc *p) { + if (!p) + return EOPNOTSUPP; p->p_stopped = 0; return 0; } @@ -236,6 +203,8 @@ S_proc_mark_cont (struct proc *p) kern_return_t S_proc_mark_traced (struct proc *p) { + if (!p) + return EOPNOTSUPP; p->p_traced = 1; return 0; } @@ -245,20 +214,10 @@ kern_return_t S_proc_mod_stopchild (struct proc *p, int value) { + if (!p) + return EOPNOTSUPP; /* VALUE is nonzero if we should send SIGCHLD. */ p->p_nostopcld = ! value; return 0; } -/* Return 1 if pid is in use by a zombie. */ -int -zombie_check_pid (pid_t pid) -{ - struct zombie *z; - for (z = zombie_list; z; z = z->next) - if (z->pid == pid || -z->pid == pid - || z->pgrp == pid || -z->pgrp == pid) - return 1; - return 0; -} - -- cgit v1.2.3