Bug 32922 - futex_wait() may ignore the timeout if interrupted by a signal
Summary: futex_wait() may ignore the timeout if interrupted by a signal
Status: CLOSED CODE_FIX
Alias: None
Product: Other
Classification: Unclassified
Component: Other (show other bugs)
Hardware: All Linux
: P1 low
Assignee: Darren Hart
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-04-09 01:34 UTC by Tim Smith
Modified: 2012-06-13 15:04 UTC (History)
4 users (show)

See Also:
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 (458 bytes, patch)
2011-04-09 01:34 UTC, Tim Smith
Details | Diff
Set the flag during do_futex() along with the other flags (1.22 KB, patch)
2011-04-14 16:57 UTC, Darren Hart
Details | Diff
V4, add flag during setup of restart block (1.66 KB, patch)
2011-04-14 21:49 UTC, Darren Hart
Details | Diff

Description Tim Smith 2011-04-09 01:34:56 UTC
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;
}
Comment 1 Andrew Morton 2011-04-09 01:49:34 UTC
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.
Comment 2 Darren Hart 2011-04-14 16:57:21 UTC
Created attachment 54372 [details]
Set the flag during do_futex() along with the other flags

Updated patch attached. Sent to LKML for review.
Comment 3 Darren Hart 2011-04-14 21:48:42 UTC
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
Comment 4 Darren Hart 2011-04-14 21:49:54 UTC
Created attachment 54392 [details]
V4, add flag during setup of restart block
Comment 5 Florian Mickler 2011-04-19 08:45:14 UTC
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

Note You need to log in before you can comment on or make changes to this bug.