lkml.org 
[lkml]   [2007]   [Feb]   [20]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[PATCH] fix handling of SIGCHILD from reaped child
    SUSv3 says
    ==
    if SIGCHLD is blocked, if wait() or waitpid() return because the status of a
    child process is available, any pending SIGCHLD signal shall be cleared unless
    the status of another child process is available.
    ==

    This patch tries to implement above functionality (clear SIGCHLD from reaped
    process.)
    please review...

    works well on 2.6.20/ia64/NUMA environment and passed my easy test.

    Signed-Off-By: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>

    Index: linux-2.6.20-devel/kernel/signal.c
    ===================================================================
    --- linux-2.6.20-devel.orig/kernel/signal.c
    +++ linux-2.6.20-devel/kernel/signal.c
    @@ -382,7 +382,7 @@ unblock_all_signals(void)
    spin_unlock_irqrestore(&current->sighand->siglock, flags);
    }

    -static int collect_signal(int sig, struct sigpending *list, siginfo_t *info)
    +static int collect_signal(int sig, struct sigpending *list, siginfo_t *info, pid_t checkpid)
    {
    struct sigqueue *q, *first = NULL;
    int still_pending = 0;
    @@ -394,13 +394,24 @@ static int collect_signal(int sig, struc
    * Collect the siginfo appropriate to this signal. Check if
    * there is another siginfo for the same signal.
    */
    - list_for_each_entry(q, &list->list, list) {
    - if (q->info.si_signo == sig) {
    - if (first) {
    - still_pending = 1;
    - break;
    + if (unlikely(checkpid)) {
    + list_for_each_entry(q, &list->list, list) {
    + if (q->info.si_signo == sig) {
    + if (q->info.si_pid == checkpid)
    + first = q;
    + else
    + still_pending = 1;
    + }
    + }
    + } else {
    + list_for_each_entry(q, &list->list, list) {
    + if (q->info.si_signo == sig) {
    + if (first) {
    + still_pending = 1;
    + break;
    + }
    + first = q;
    }
    - first = q;
    }
    }
    if (first) {
    @@ -415,7 +426,8 @@ static int collect_signal(int sig, struc
    a fast-pathed signal or we must have been
    out of queue space. So zero out the info.
    */
    - sigdelset(&list->signal, sig);
    + if (!still_pending)
    + sigdelset(&list->signal, sig);
    info->si_signo = sig;
    info->si_errno = 0;
    info->si_code = 0;
    @@ -440,7 +452,7 @@ static int __dequeue_signal(struct sigpe
    }
    }

    - if (!collect_signal(sig, pending, info))
    + if (!collect_signal(sig, pending, info, 0))
    sig = 0;
    }

    @@ -493,6 +505,24 @@ int dequeue_signal(struct task_struct *t
    }

    /*
    + * only called by do_wait() when it reaps its child.
    + * This function clears pending SIGCHLD from the reaped child.
    + * rerely does real job...
    + * Becasue we only check SIGCHLD, just checks shared_pending.
    + */
    +void clear_stale_sigchild(struct task_struct *tsk, pid_t child_id)
    +{
    + siginfo_t info;
    + unsigned long flags;
    + spin_lock_irqsave(&tsk->sighand->siglock, flags);
    + collect_signal(SIGCHLD, &tsk->signal->shared_pending, &info, child_id);
    + spin_unlock_irqrestore(&tsk->sighand->siglock, flags);
    + return;
    +}
    +
    +
    +
    +/*
    * Tell a process that it has a new active signal..
    *
    * NOTE! we rely on the previous spin_lock to
    Index: linux-2.6.20-devel/kernel/exit.c
    ===================================================================
    --- linux-2.6.20-devel.orig/kernel/exit.c
    +++ linux-2.6.20-devel/kernel/exit.c
    @@ -1252,8 +1252,12 @@ static int wait_task_zombie(struct task_
    }
    write_unlock_irq(&tasklist_lock);
    }
    - if (p != NULL)
    + if (p != NULL) {
    release_task(p);
    + /* if we received sigchild from "p" and p is released,
    + we remove sigchild from it. */
    + clear_stale_sigchild(current, retval);
    + }
    BUG_ON(!retval);
    return retval;
    }
    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

    \
     
     \ /
      Last update: 2007-02-20 10:37    [W:0.047 / U:0.036 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site