summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--proc/Makefile15
-rw-r--r--proc/host.c24
-rw-r--r--proc/info.c49
-rw-r--r--proc/main.c62
-rw-r--r--proc/msg.c43
-rw-r--r--proc/notify.c22
-rw-r--r--proc/pgrp.c24
-rw-r--r--proc/proc.h34
-rw-r--r--proc/wait.c127
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 <hurd.h>
#include <hurd/startup.h>
#include <assert.h>
+#include <wire.h>
#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 <mach.h>
#include <hurd.h>
#include "proc.h"
-#include "process_reply_U.h"
#include <hurd/startup.h>
#include <assert.h>
#include <stdlib.h>
@@ -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 <sys/resource.h>
+#include <hurd/ports.h>
+#include <cthreads.h>
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 <assert.h>
#include "process_S.h"
-#include "process_reply_U.h"
-#include "ourmsg_U.h"
-
#include <mach/mig_errors.h>
/* 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 <hurd/proc.defs>. */
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;
-}
-