[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH hurd 3/5] proc: implement `proc_make_task_namespace'
From: |
Samuel Thibault |
Subject: |
Re: [PATCH hurd 3/5] proc: implement `proc_make_task_namespace' |
Date: |
Wed, 10 Dec 2014 01:45:40 +0100 |
User-agent: |
Mutt/1.5.21+34 (58baf7c9f32f) (2010-12-30) |
Justus Winter, le Thu 13 Nov 2014 13:26:17 +0100, a écrit :
> * proc/proc.h (struct proc): Add field `p_task_namespace'.
> * proc/mgt.c (S_proc_child): Propagate `p_task_namespace' to child.
> (allocate_proc): Initialize `p_task_namespace'.
> (namespace_terminate): New function.
> (process_has_exited): Reparent children of dead tasks in the namespace
> to the root process. Terminate all tasks if the root process dies.
> Reap dead tasks.
> (S_mach_notify_new_task): For newly created tasks thats parent is in a
> namespace, call S_proc_child and forward the `mach_notify_new_task'
> message.
> (S_proc_make_task_namespace): New function.
Ack.
> ---
> proc/mgt.c | 112
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
> proc/proc.h | 4 +++
> 2 files changed, 107 insertions(+), 9 deletions(-)
>
> diff --git a/proc/mgt.c b/proc/mgt.c
> index 32408ae..bf400ba 100644
> --- a/proc/mgt.c
> +++ b/proc/mgt.c
> @@ -220,6 +220,13 @@ S_proc_child (struct proc *parentp,
> childp->end_code = parentp->end_code;
> }
>
> + if (MACH_PORT_VALID (parentp->p_task_namespace))
> + {
> + mach_port_mod_refs (mach_task_self (), parentp->p_task_namespace,
> + MACH_PORT_RIGHT_SEND, +1);
> + childp->p_task_namespace = parentp->p_task_namespace;
> + }
> +
> return 0;
> }
>
> @@ -577,6 +584,7 @@ allocate_proc (task_t task)
>
> memset (&p->p_pi + 1, 0, sizeof *p - sizeof p->p_pi);
> p->p_task = task;
> + p->p_task_namespace = MACH_PORT_NULL;
> p->p_msgport = MACH_PORT_NULL;
>
> pthread_cond_init (&p->p_wakeup, NULL);
> @@ -721,6 +729,16 @@ new_proc (task_t task)
> return p;
> }
>
> +/* Used with prociterate to terminate all tasks in a task
> + namespace. */
> +static void
> +namespace_terminate (struct proc *p, void *cookie)
> +{
> + mach_port_t *namespacep = cookie;
> + if (p->p_task_namespace == *namespacep)
> + task_terminate (p->p_task);
> +}
> +
> /* The task associated with process P has died. Drop most state,
> and then record us as dead. Our parent will eventually complete the
> deallocation. */
> @@ -751,13 +769,39 @@ process_has_exited (struct proc *p)
>
> ids_rele (p->p_id);
>
> - /* Reparent our children to init by attaching the head and tail
> - of our list onto init's. */
> + /* Reparent our children to init by attaching the head and tail of
> + our list onto init's. If the process is part of a task
> + namespace, reparent to the process that created the namespace
> + instead. */
> if (p->p_ochild)
> {
> + struct proc *reparent_to = init_proc;
> struct proc *tp; /* will point to the last one. */
> int isdead = 0;
>
> + if (MACH_PORT_VALID (p->p_task_namespace))
> + {
> + for (tp = p;
> + MACH_PORT_VALID (tp->p_parent->p_task_namespace);
> + tp = tp->p_parent)
> + {
> + /* Walk up the process hierarchy until we find the
> + creator of the task namespace. */
> + }
> +
> + if (p == tp)
> + {
> + /* The creator of the task namespace died. Terminate
> + all tasks. */
> + prociterate (namespace_terminate, &p->p_task_namespace);
> +
> + mach_port_deallocate (mach_task_self (), p->p_task_namespace);
> + p->p_task_namespace = MACH_PORT_NULL;
> + }
> + else
> + reparent_to = tp;
> + }
> +
> /* first tell them their parent is changing */
> for (tp = p->p_ochild; tp->p_sib; tp = tp->p_sib)
> {
> @@ -765,7 +809,7 @@ process_has_exited (struct proc *p)
> nowait_msg_proc_newids (tp->p_msgport, tp->p_task,
> 1, tp->p_pgrp->pg_pgid,
> !tp->p_pgrp->pg_orphcnt);
> - tp->p_parent = init_proc;
> + tp->p_parent = reparent_to;
> if (tp->p_dead)
> isdead = 1;
> }
> @@ -773,17 +817,17 @@ process_has_exited (struct proc *p)
> nowait_msg_proc_newids (tp->p_msgport, tp->p_task,
> 1, tp->p_pgrp->pg_pgid,
> !tp->p_pgrp->pg_orphcnt);
> - tp->p_parent = init_proc;
> + tp->p_parent = reparent_to;
>
> /* And now append the lists. */
> - tp->p_sib = init_proc->p_ochild;
> + tp->p_sib = reparent_to->p_ochild;
> if (tp->p_sib)
> tp->p_sib->p_prevsib = &tp->p_sib;
> - init_proc->p_ochild = p->p_ochild;
> - p->p_ochild->p_prevsib = &init_proc->p_ochild;
> + reparent_to->p_ochild = p->p_ochild;
> + p->p_ochild->p_prevsib = &reparent_to->p_ochild;
>
> if (isdead)
> - alert_parent (init_proc);
> + alert_parent (reparent_to);
> }
>
> /* If an operation is in progress for this process, cause it
> @@ -795,6 +839,23 @@ process_has_exited (struct proc *p)
>
> /* Cancel any outstanding RPCs done on behalf of the dying process. */
> ports_interrupt_rpcs (p);
> +
> + /* No one is going to wait for processes in a task namespace. */
> + if (MACH_PORT_VALID (p->p_task_namespace))
> + {
> + mach_port_t task;
> + mach_port_deallocate (mach_task_self (), p->p_task_namespace);
> + p->p_waited = 1;
> +
> + /* XXX: `complete_exit' will destroy p->p_task if it is valid.
> + Prevent this so that `do_mach_notify_dead_name' can
> + deallocate the right. The proper fix is not to use
> + mach_port_destroy in the first place. */
> + task = p->p_task;
> + p->p_task = MACH_PORT_NULL;
> + complete_exit (p);
> + mach_port_deallocate (mach_task_self (), task);
> + }
> }
>
> void
> @@ -1008,9 +1069,42 @@ S_mach_notify_new_task (mach_port_t notify,
> childp = new_proc (task);
> }
>
> - /* XXX do something interesting */
> + if (MACH_PORT_VALID (parentp->p_task_namespace))
> + {
> + error_t err;
> + /* Tasks in a task namespace are not expected to call
> + proc_child, so we do it on their behalf. */
> + mach_port_mod_refs (mach_task_self (), task, MACH_PORT_RIGHT_SEND, +1);
> + err = S_proc_child (parentp, task);
> + if (! err)
> + /* Relay the notification. This consumes TASK and PARENT. */
> + return mach_notify_new_task (childp->p_task_namespace, task, parent);
> + }
>
> mach_port_deallocate (mach_task_self (), task);
> mach_port_deallocate (mach_task_self (), parent);
> return 0;
> }
> +
> +/* Implement proc_make_task_namespace as described in
> + <hurd/process.defs>. */
> +error_t
> +S_proc_make_task_namespace (struct proc *callerp,
> + mach_port_t notify)
> +{
> + if (! callerp)
> + return EOPNOTSUPP;
> +
> + if (! MACH_PORT_VALID (notify))
> + return EINVAL;
> +
> + if (MACH_PORT_VALID (callerp->p_task_namespace))
> + {
> + mach_port_deallocate (mach_task_self (), notify);
> + return EBUSY;
> + }
> +
> + callerp->p_task_namespace = notify;
> +
> + return 0;
> +}
> diff --git a/proc/proc.h b/proc/proc.h
> index 6196697..a056d18 100644
> --- a/proc/proc.h
> +++ b/proc/proc.h
> @@ -58,6 +58,10 @@ struct proc
> /* Process group structure */
> struct pgrp *p_pgrp;
>
> + /* Processes may live in a task namespace identified by the
> + notification port registered by proc_make_task_namespace. */
> + mach_port_t p_task_namespace; /* send right */
> +
> /* Communication */
> mach_port_t p_msgport; /* send right */
>
> --
> 2.1.1
>
--
Samuel
SL> Au fait elle est mieux ma signature maintenant ?
Oui. T'enlève encore les conneries que t'as écrit dedans et c'est bon.
-+- JB in <http://neuneu.mine.nu> : Le neueuttoyage par le vide -+-
- Re: [PATCH hurd 3/5] proc: implement `proc_make_task_namespace',
Samuel Thibault <=