#1000978 datefudge: fails to adjust pthread_cond_timedwait()

Package:
datefudge
Source:
datefudge
Description:
Fake the system date
Submitter:
Anders Kaseorg
Date:
2021-12-02 02:15:04 UTC
Severity:
normal
#1000978#5
Date:
2021-12-02 02:05:17 UTC
From:
To:
The test programs below should sleep for 2 seconds. However, under datefudge '1 second', they actually sleep for 3 seconds, and under datefudge '1 second ago', they only sleep for 1 second. This seems to be because datefudge adjusts the clock_gettime() call, but not the pthread_cond_timedwait() call or the futex() call that implements it.

I noticed this while using threading.Thread.join(timeout) in Python 3.6. (Python 3.8 has since changed that to use CLOCK_MONOTONIC: https://bugs.python.org/issue12822.)

First test program, using pthread_cond_timedwait() (compile with gcc -pthread):

#include <pthread.h>
#include <stdio.h>
#include <time.h>

int main() {
  pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
  pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
  pthread_mutex_lock(&mutex);
  struct timespec timeout;
  clock_gettime(CLOCK_REALTIME, &timeout);
  timeout.tv_sec += 2;
  printf("sleeping\n");
  pthread_cond_timedwait(&cond, &mutex, &timeout);
  printf("done\n");
  return 0;
}

Second test program, using futex() directly:

#include <linux/futex.h>
#include <stdint.h>
#include <stdio.h>
#include <sys/syscall.h>
#include <time.h>
#include <unistd.h>

int main() {
  uint32_t u = 123;
  struct timespec timeout;
  clock_gettime(CLOCK_REALTIME, &timeout);
  timeout.tv_sec += 2;
  printf("sleeping\n");
  syscall(SYS_futex, &u, FUTEX_WAIT_BITSET | FUTEX_CLOCK_REALTIME, 123,
          &timeout, FUTEX_BITSET_MATCH_ANY);
  printf("done\n");
  return 0;
}