summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--proc/mgt.c173
1 files changed, 97 insertions, 76 deletions
diff --git a/proc/mgt.c b/proc/mgt.c
index 853e53db..da98d325 100644
--- a/proc/mgt.c
+++ b/proc/mgt.c
@@ -1,5 +1,5 @@
/* Process management
- Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
This file is part of the GNU Hurd.
@@ -8,7 +8,7 @@ it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
-The GNU Hurd is distributed in the hope that it will be useful,
+The GNU Hurd is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
@@ -37,22 +37,21 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "ourmsg_U.h"
#include "proc_exc_S.h"
#include "proc_exc_U.h"
-#include "proc_excrepl_U.h"
-#include "proc_excrepl_S.h"
+#include <hurd/signal.h>
/* Create a new id structure with the given genuine uids and gids. */
static inline struct ids *
make_ids (uid_t *uids, int nuids, uid_t *gids, int ngids)
{
struct ids *i;
-
+
i = malloc (sizeof (struct ids));
i->i_nuids = nuids;
i->i_ngids = ngids;
i->i_uids = malloc (sizeof (uid_t) * nuids);
i->i_gids = malloc (sizeof (uid_t) * ngids);
i->i_refcnt = 1;
-
+
memcpy (i->i_uids, uids, sizeof (uid_t) * nuids);
memcpy (i->i_gids, gids, sizeof (uid_t) * ngids);
return i;
@@ -87,17 +86,17 @@ S_proc_reauthenticate (struct proc *p, mach_port_t rendport)
uid_t gubuf[50], aubuf[50], ggbuf[50], agbuf[50];
uid_t *gen_uids, *aux_uids, *gen_gids, *aux_gids;
u_int ngen_uids, naux_uids, ngen_gids, naux_gids;
-
+
gen_uids = gubuf;
aux_uids = aubuf;
gen_gids = ggbuf;
aux_gids = agbuf;
-
+
ngen_uids = naux_uids = 50;
ngen_gids = naux_gids = 50;
- err = auth_server_authenticate (authserver, p->p_reqport,
- MACH_MSG_TYPE_MAKE_SEND,
+ err = auth_server_authenticate (authserver, p->p_reqport,
+ MACH_MSG_TYPE_MAKE_SEND,
rendport, MACH_MSG_TYPE_MOVE_SEND,
MACH_PORT_NULL, MACH_MSG_TYPE_COPY_SEND,
&gen_uids, &ngen_uids,
@@ -110,7 +109,7 @@ S_proc_reauthenticate (struct proc *p, mach_port_t rendport)
if (!--p->p_id->i_refcnt)
free_ids (p->p_id);
p->p_id = make_ids (gen_uids, ngen_uids, gen_gids, ngen_gids);
-
+
if (gen_uids != gubuf)
vm_deallocate (mach_task_self (), (u_int) gen_uids,
ngen_uids * sizeof (uid_t));
@@ -136,10 +135,10 @@ S_proc_child (struct proc *parentp,
if (!childp)
return ESRCH;
-
+
if (childp->p_parentset)
return EBUSY;
-
+
/* Process identification.
Leave p_task and p_pid alone; all the rest comes from the
new parent. */
@@ -157,14 +156,14 @@ S_proc_child (struct proc *parentp,
childp->p_id = parentp->p_id;
childp->p_id->i_refcnt++;
- /* Process hierarchy. Remove from our current location
+ /* Process hierarchy. Remove from our current location
and place us under our new parent. Sanity check to make sure
parent is currently init. */
assert (childp->p_parent == startup_proc);
if (childp->p_sib)
childp->p_sib->p_prevsib = childp->p_prevsib;
*childp->p_prevsib = childp->p_sib;
-
+
childp->p_parent = parentp;
childp->p_sib = parentp->p_ochild;
childp->p_prevsib = &parentp->p_ochild;
@@ -172,7 +171,7 @@ S_proc_child (struct proc *parentp,
parentp->p_ochild->p_prevsib = &childp->p_sib;
parentp->p_ochild = childp;
- /* Process group structure. */
+ /* Process group structure. */
if (childp->p_pgrp != parentp->p_pgrp)
{
leave_pgrp (childp);
@@ -182,7 +181,7 @@ S_proc_child (struct proc *parentp,
it for us. */
}
else if (childp->p_msgport != MACH_PORT_NULL)
- nowait_msg_proc_newids (childp->p_msgport, childp->p_task,
+ nowait_msg_proc_newids (childp->p_msgport, childp->p_task,
childp->p_parent->p_pid, childp->p_pgrp->pg_pgid,
!childp->p_pgrp->pg_orphcnt);
childp->p_parentset = 1;
@@ -199,7 +198,7 @@ S_proc_reassign (struct proc *p,
if (!stubp)
return ESRCH;
-
+
if (stubp == p)
return EINVAL;
@@ -209,7 +208,7 @@ S_proc_reassign (struct proc *p,
mach_port_deallocate (mach_task_self (), p->p_task);
p->p_task = newt;
- /* For security, we need use the request port from STUBP, and
+ /* For security, we need use the request port from STUBP, and
not inherit this state. */
mach_port_mod_refs (mach_task_self (), p->p_reqport,
MACH_PORT_RIGHT_RECEIVE, -1);
@@ -240,7 +239,7 @@ S_proc_reassign (struct proc *p,
/* Destroy stubp */
stubp->p_task = 0; /* block deallocation */
process_has_exited (stubp);
-
+
add_proc_to_hash (p);
return 0;
@@ -253,7 +252,7 @@ S_proc_setowner (struct proc *p,
{
if (! check_uid (p, owner))
return EPERM;
-
+
p->p_owner = owner;
p->p_noowner = 0;
return 0;
@@ -338,7 +337,7 @@ S_proc_handle_exceptions (struct proc *p,
struct exc *e = malloc (sizeof (struct exc)
+ (statecnt * sizeof (natural_t)));
mach_port_t foo;
-
+
mach_port_request_notification (mach_task_self (), msgport,
MACH_NOTIFY_NO_SENDERS, 1, msgport,
MACH_MSG_TYPE_MAKE_SEND_ONCE, &foo);
@@ -348,7 +347,6 @@ S_proc_handle_exceptions (struct proc *p,
mach_port_move_member (mach_task_self (), msgport, request_portset);
e->excport = msgport;
e->forwardport = forwardport;
- e->replyport = MACH_PORT_NULL;
e->flavor = flavor;
e->statecnt = statecnt;
bcopy (new_state, e->thread_state, statecnt * sizeof (natural_t));
@@ -362,41 +360,64 @@ S_proc_handle_exceptions (struct proc *p,
kern_return_t
S_proc_exception_raise (mach_port_t excport,
mach_port_t reply,
- mach_msg_type_name_t replyname,
+ mach_msg_type_name_t reply_type,
mach_port_t thread,
mach_port_t task,
int exception,
int code,
int subcode)
{
+ error_t err;
+ struct proc *p;
struct exc *e = exc_find (excport);
if (!e)
return EOPNOTSUPP;
- if (e->replyport != MACH_PORT_NULL)
- return EBUSY; /* This is wrong, but too much trouble to fix now */
- thread_set_state (thread, e->flavor, e->thread_state, e->statecnt);
- proc_exception_raise (e->forwardport, e->excport,
- MACH_MSG_TYPE_MAKE_SEND_ONCE,
- thread, task, exception, code, subcode);
+
+ p = task_find (task);
+ if (! p)
+ /* Bogus RPC. */
+ return EINVAL;
+
+ /* Try to forward the message. */
+ err = proc_exception_raise (e->forwardport,
+ reply, reply_type, MACH_SEND_NOTIFY,
+ thread, task, exception, code, subcode);
mach_port_deallocate (mach_task_self (), thread);
mach_port_deallocate (mach_task_self (), task);
- return MIG_NO_REPLY;
-}
-/* Called by proc_handle_exception clients after they have received
- the exception_raise we send in S_proc_exception_raise. Reply to
- the agent that generated the exception raise. */
-kern_return_t
-S_proc_exception_raise_reply (mach_port_t excport,
- int replycode)
-{
- struct exc *e = exc_find (excport);
- if (!e)
- return EOPNOTSUPP;
- if (e->replyport == MACH_PORT_NULL)
- return 0;
- proc_exception_raise_reply (e->replyport, e->replyporttype, replycode);
- return MIG_NO_REPLY;
+ switch (err)
+ {
+ int signo, error;
+ long int sigcode;
+
+ case 0:
+ /* We have successfully forwarded the exception message. Now reset
+ the faulting thread's state to run its recovery code, which should
+ dequeue that message. */
+ err = thread_set_state (thread, e->flavor, e->thread_state, e->statecnt);
+ return MIG_NO_REPLY;
+
+ default:
+ /* Some unexpected error in forwarding the message. */
+ /* FALLTHROUGH */
+
+ case MACH_SEND_INVALID_NOTIFY:
+ /* The port's queue is full, meaning the thread didn't receive
+ the exception message we forwarded last time it faulted.
+ Declare that signal thread hopeless and the task crashed. */
+
+ /* Translate the exception code into a signal number
+ and mark the process has dying that way. */
+ _hurd_exception2signal (exception, code, subcode,
+ &signo, &sigcode, &error);
+ p->p_exiting = 1;
+ p->p_status = W_EXITCODE (0, signo);
+
+ /* Nuke the task; we will get a notification message and report it
+ died with SIGNO. */
+ task_terminate (task);
+ return 0;
+ }
}
/* Implement proc_getallpids as described in <hurd/proc.defs>. */
@@ -407,7 +428,7 @@ S_proc_getallpids (struct proc *p,
{
int nprocs;
pid_t *loc;
-
+
void count_up (struct proc *p, void *counter)
{
++*(int *)counter;
@@ -418,7 +439,7 @@ S_proc_getallpids (struct proc *p,
}
add_tasks (0);
-
+
nprocs = 0;
prociterate (count_up, &nprocs);
@@ -440,12 +461,12 @@ new_proc (task_t task)
{
struct proc *p;
mach_port_t foo;
-
+
/* Because these have a reference count of one before starting,
they can never be freed, so we're safe. */
static struct login *nulllogin;
static struct ids nullids = {0, 0, 0, 0, 1};
-
+
if (!nulllogin)
{
nulllogin = malloc (sizeof (struct login) + 7);
@@ -460,7 +481,7 @@ new_proc (task_t task)
p = malloc (sizeof (struct proc));
mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE,
&p->p_reqport);
- mach_port_move_member (mach_task_self (), p->p_reqport,
+ mach_port_move_member (mach_task_self (), p->p_reqport,
request_portset);
p->p_pid = genpid ();
@@ -470,8 +491,8 @@ new_proc (task_t task)
MACH_MSG_TYPE_MAKE_SEND_ONCE, &foo);
if (foo != MACH_PORT_NULL)
mach_port_deallocate (mach_task_self (), foo);
-
-
+
+
switch (p->p_pid)
{
case 0:
@@ -479,7 +500,7 @@ new_proc (task_t task)
p->p_login->l_refcnt = 1;
strcpy (p->p_login->l_name, "root");
break;
-
+
case 1:
p->p_login = self_proc->p_login;
p->p_login->l_refcnt++;
@@ -489,9 +510,9 @@ new_proc (task_t task)
p->p_login = nulllogin;
p->p_login->l_refcnt++;
}
-
+
p->p_owner = 0;
-
+
if (p->p_pid == 0)
{
uid_t foo = 0;
@@ -538,16 +559,16 @@ new_proc (task_t task)
p->p_parentset = 0;
p->p_noowner = 1;
}
-
+
if (p->p_pid < 2)
boot_setsid (p);
else
p->p_pgrp = startup_proc->p_pgrp;
-
+
p->p_msgport = MACH_PORT_NULL;
-
+
p->p_argv = p->p_envp = p->p_status = 0;
-
+
p->p_exec = 0;
p->p_stopped = 0;
p->p_waited = 0;
@@ -576,26 +597,26 @@ process_has_exited (struct proc *p)
alert_parent (p);
prociterate ((void (*) (struct proc *, void *))check_message_dying, p);
-
- mach_port_mod_refs (mach_task_self (), p->p_reqport,
+
+ mach_port_mod_refs (mach_task_self (), p->p_reqport,
MACH_PORT_RIGHT_RECEIVE, -1);
remove_proc_from_hash (p);
-
+
mach_port_deallocate (mach_task_self (), p->p_task);
if (!--p->p_login->l_refcnt)
free (p->p_login);
-
+
if (!--p->p_id->i_refcnt)
free_ids (p->p_id);
-
- /* Reparent our children to init by attaching the head and tail
+
+ /* Reparent our children to init by attaching the head and tail
of our list onto init's. */
if (p->p_ochild)
{
struct proc *tp; /* will point to the last one */
-
+
/* first tell them their parent is changing */
for (tp = p->p_ochild; tp->p_sib; tp = tp->p_sib)
{
@@ -620,23 +641,23 @@ process_has_exited (struct proc *p)
}
reparent_zombies (p);
-
+
/* Remove us from our parent's list of children. */
if (p->p_sib)
p->p_sib->p_prevsib = p->p_prevsib;
*p->p_prevsib = p->p_sib;
-
+
leave_pgrp (p);
-
+
mach_port_deallocate (mach_task_self (), p->p_msgport);
-
+
if (p->p_waiting)
- mach_port_deallocate (mach_task_self (),
+ mach_port_deallocate (mach_task_self (),
p->p_continuation.wait_c.reply_port);
if (p->p_msgportwait)
mach_port_deallocate (mach_task_self (),
p->p_continuation.getmsgport_c.reply_port);
-
+
free (p);
}
@@ -687,18 +708,18 @@ add_tasks (task_t task)
}
mach_port_deallocate (mach_task_self (), psets[i]);
}
- vm_deallocate (mach_host_self (), (vm_address_t) psets,
+ vm_deallocate (mach_host_self (), (vm_address_t) psets,
npsets * sizeof (mach_port_t));
return foundp;
}
/* Allocate a new pid. The first two times this is called it must return
- 0 and 1 in order; after that it must simply return an unused pid.
+ 0 and 1 in order; after that it must simply return an unused pid.
(Unused means it is neither the pid nor pgrp of any relevant data.) */
int
genpid ()
{
-#define WRAP_AROUND 30000
+#define WRAP_AROUND 30000
#define START_OVER 100
static int nextpid = 0;
static int wrap = WRAP_AROUND;