From mboxrd@z Thu Jan 1 00:00:00 1970 From: Mark Kettenis To: gdb-patches@sources.redhat.com Subject: [PATCH] lin-lwp fix Date: Thu, 12 Jul 2001 12:39:00 -0000 Message-id: <200107121939.f6CJdjX17252@delius.kettenis.local> X-SW-Source: 2001-07/msg00308.html I origionally came up with this patch to fix a intermittent test failure in gdb.threads/pthreads.exp: FAIL: gdb.threads/pthreads.exp: Stopped with a ^C (timeout) WARNING: Could not stop child with ^C; skipping rest of tests. It doesn't fix the problem, but I think it makes the code more robust and it adds a nice feature that can be used for other smart optimizations. Check in. Mark Index: ChangeLog from Mark Kettenis * lin-lwp.c (stop_wait_callback): Add support for flushing signals. Use that in favour of the old code to get rid of superfluous SIGINTs. (lin_lwp_wait): Use the new support in stop_wait_callback to flush all but one SIGINT. Index: lin-lwp.c =================================================================== RCS file: /cvs/src/src/gdb/lin-lwp.c,v retrieving revision 1.27 diff -u -p -r1.27 lin-lwp.c --- lin-lwp.c 2001/07/07 10:58:37 1.27 +++ lin-lwp.c 2001/07/12 19:34:59 @@ -595,11 +595,14 @@ stop_callback (struct lwp_info *lp, void return 0; } -/* Wait until LP is stopped. */ +/* Wait until LP is stopped. If DATA is non-null it is interpreted as + a pointer to a set of signals to be flushed immediately. */ static int stop_wait_callback (struct lwp_info *lp, void *data) { + sigset_t *flush_mask = data; + if (! lp->stopped && lp->signalled) { pid_t pid; @@ -639,6 +642,13 @@ stop_wait_callback (struct lwp_info *lp, gdb_assert (WIFSTOPPED (status)); + /* Ignore any signals in FLUSH_MASK. */ + if (flush_mask && sigismember (flush_mask, WSTOPSIG (status))) + { + ptrace (PTRACE_CONT, GET_LWP (lp->ptid), 0, 0); + return stop_wait_callback (lp, flush_mask); + } + if (WSTOPSIG (status) != SIGSTOP) { if (WSTOPSIG (status) == SIGTRAP) @@ -673,18 +683,6 @@ stop_wait_callback (struct lwp_info *lp, lp->status = status; return 0; } - else if (WSTOPSIG (status) == SIGINT && - signal_pass_state (SIGINT) == 0) - { - /* Since SIGINT gets forwarded to the entire process group - (in the case where ^C/BREAK is typed at the tty/console), - just ignore all SIGINT events from all lwp's except for - the one that was caught by lin_lwp_wait. */ - - /* Now resume this LWP and get the SIGSTOP event. */ - ptrace (PTRACE_CONT, GET_LWP (lp->ptid), 0, 0); - return stop_wait_callback (lp, data); - } else { /* The thread was stopped with a signal other than @@ -897,6 +895,9 @@ lin_lwp_wait (ptid_t ptid, struct target int options = 0; int status = 0; pid_t pid = PIDGET (ptid); + sigset_t flush_mask; + + sigemptyset (&flush_mask); /* Make sure SIGCHLD is blocked. */ if (! sigismember (&blocked_mask, SIGCHLD)) @@ -1113,6 +1114,16 @@ lin_lwp_wait (ptid_t ptid, struct target status = 0; goto retry; } + + if (signo == TARGET_SIGNAL_INT + && signal_pass_state (signo) == 0) + { + /* If ^C/BREAK is typed at the tty/console, SIGINT gets + forwarded to the entire process group, that is, all LWP's + will receive it. Since we only want to report it once, + we try to flush it from all LWPs except this one. */ + sigaddset (&flush_mask, SIGINT); + } } /* This LWP is stopped now. */ @@ -1127,7 +1138,7 @@ lin_lwp_wait (ptid_t ptid, struct target /* ... and wait until all of them have reported back that they're no longer running. */ - iterate_over_lwps (stop_wait_callback, NULL); + iterate_over_lwps (stop_wait_callback, &flush_mask); /* If we're not waiting for a specific LWP, choose an event LWP from among those that have had events. Giving equal priority to all