Bug 32922
Summary: | futex_wait() may ignore the timeout if interrupted by a signal | ||
---|---|---|---|
Product: | Other | Reporter: | Tim Smith (tsmith201104) |
Component: | Other | Assignee: | Darren Hart (kernel-bugs) |
Status: | CLOSED CODE_FIX | ||
Severity: | low | CC: | akpm, alan, florian, kernel-bugs |
Priority: | P1 | ||
Hardware: | All | ||
OS: | Linux | ||
Kernel Version: | 2.6.38.2 | Subsystem: | |
Regression: | Yes | Bisected commit-id: | |
Attachments: |
Fixes a bug in futex_wait() that causes timeouts to be ignored
Set the flag during do_futex() along with the other flags V4, add flag during setup of restart block |
Please send the patch via email, not via bugzilla. Suitable recipients are Thomas Gleixner <tglx@linutronix.de> Darren Hart <dvhart@linux.intel.com> linux-kernel@vger.kernel.org stable@kernel.org Andrew Morton <akpm@linux-foundation.org> As it's a regression, please also include a Cc: <stable@kernel.org> in the changelog. Created attachment 54372 [details]
Set the flag during do_futex() along with the other flags
Updated patch attached. Sent to LKML for review.
After some discussion with Eric Dumazet, the final submitted patch simply ORs the FLAGS_HAS_TIMEOUT during setup of the restart block. https://lkml.org/lkml/2011/4/14/640 Created attachment 54392 [details]
V4, add flag during setup of restart block
A patch referencing this bug report has been merged in v2.6.39-rc4: commit 0cd9c6494ee5c19aef085152bc37f3a4e774a9e1 Author: Darren Hart <dvhart@linux.intel.com> Date: Thu Apr 14 15:41:57 2011 -0700 futex: Set FLAGS_HAS_TIMEOUT during futex_wait restart setup |
Created attachment 53882 [details] Fixes a bug in futex_wait() that causes timeouts to be ignored I noticed after starting a program from an xterm and trying to put it in the background that it would not resume. In kernel/futex.c line 1889 restart->futex.flags needs FLAGS_HAS_TIMEOUT or the timeout gets ignored after futex_wait() is interrupted by a signal. The code below triggers it on my Slackware64 13.1 system (glibc-2.11.1). #include <stdio.h> #include <pthread.h> #include <time.h> #include <unistd.h> #include <sys/types.h> #include <signal.h> int main (void) { pthread_condattr_t ca; pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t cv; struct timespec ts; pid_t p; int i; if ( (p = fork()) != 0 ) { printf("Child is running\n"); sleep(3); kill(p, SIGSTOP); printf("Child is stopped\n"); sleep(3); kill(p, SIGCONT); printf("Child should have resumed\n"); sleep(3); kill(p, SIGINT); return 0; } pthread_condattr_init(&ca); pthread_condattr_setclock(&ca, CLOCK_MONOTONIC); pthread_cond_init(&cv, &ca); while(1) { clock_gettime(CLOCK_MONOTONIC, &ts); printf("SLEEP: %lu\n", ts.tv_sec); ts.tv_sec++; pthread_cond_timedwait(&cv, &mut, &ts); clock_gettime(CLOCK_MONOTONIC, &ts); printf("WAKE: %lu\n", ts.tv_sec); } return 0; }