8 Commits

4 changed files with 97 additions and 7 deletions

26
README
View File

@@ -1,5 +1,5 @@
libfaketime, version 0.9.10 (February 2022)
===========================================
libfaketime, version 0.9.10 (March 2022)
========================================
Content of this file:
@@ -103,6 +103,28 @@ documentation whether it can be achieved by using libfaketime directly.
FORCE_MONOTONIC_FIX alone does not solve the hang on the MONOTONIC_CLOCK
test.
If FORCE_MONOTONIC_FIX was not set as a compile-time flag, you can also
set an environment variable FAKETIME_FORCE_MONOTONIC_FIX=1 if you want
to enable the fix at run-time, or to 0 if you explicitly want to disable
it. The fix is automatically enabled if libfaketime was compiled on a
system with glibc as the underlying libc implementation, and a glibc
version is detected at run-time that is assumed to need this workaround.
Please use Github issues at https://github.com/wolfcw/libfaketime/issues
to report any observed hangs during CLOCK_MONOTONIC tests and report
your CPU architecture, libc implementation (e.g., glibc 2.30) and any
other details that might help (e.g., Linux distribution, use within, e.g.,
Docker containers etc.).
Please try to avoid compiling with FORCE_MONOTONIC_FIX on platforms that
do not need it. While it won't make a difference in most cases, depending
on the specific FAKETIME settings in use, it would cause certain
intercepted functions such as pthread_cond_timedwait() return with a
time-out too early or too late, which could break some applications.
Try compiling without FORCE_MONOTONIC_FIX first and check whether the
tests appear to hang. If they do, you can either set the
FAKETIME_FORCE_MONOTONIC_FIX environment variable to 1, or re-compile
with FORCE_MONOTONIC_FIX set.
3. Installation
---------------

View File

@@ -1,4 +1,4 @@
.TH FAKETIME "1" "February 2022" "faketime 0.9.10" wolfcw
.TH FAKETIME "1" "March 2022" "faketime 0.9.10" wolfcw
.SH NAME
faketime \- manipulate the system time for a given command
.SH SYNOPSIS

View File

@@ -33,6 +33,11 @@
#ifdef __linux__
#include <sys/epoll.h>
#endif
#ifdef __GLIBC__
#ifndef __APPLE__
#include <gnu/libc-version.h>
#endif
#endif
#include <time.h>
#ifdef MACOS_DYLD_INTERPOSE
#include <sys/time.h>
@@ -3560,7 +3565,63 @@ int pthread_cond_destroy_232(pthread_cond_t *cond)
return real_pthread_cond_destroy_232(cond);
}
//where init in pthread methods????
/*
* Check whether we need a run-time activation of the
* forced monotonic fix to avoid faked / unfaked timestamp
* confusion between the application and glibc internals.
*/
bool needs_forced_monotonic_fix(char *function_name)
{
bool result = false;
char *env_var;
#ifdef __GLIBC__
const char *glibc_version_string = gnu_get_libc_version();
#endif
if (function_name == NULL) return false;
/* The forced monotonic fix can be activated by setting an
* environment variable to 1, or disabled by setting it to 0 */
if ((env_var = getenv("FAKETIME_FORCE_MONOTONIC_FIX")) != NULL)
{
if (env_var[0] == '0')
result = false;
else
result = true;
}
else
{
#ifdef __GLIBC__
/* Here we try to derive the necessity for a forced monotonic fix *
* based on glibc version. What could possibly go wrong? */
int glibc_major, glibc_minor;
sscanf(glibc_version_string, "%d.%d", &glibc_major, &glibc_minor);
/* The following decision logic is yet purely based on experiences
* with pthread_cond_timedwait(). The used boundaries may still be
* imprecise. */
if ( (glibc_major == 2) &&
((glibc_minor <= 24) || (glibc_minor >= 30)) )
{
result = true;
}
else
#endif
result = false; // avoid forced monotonic fixes unless really necessary
}
if (getenv("FAKETIME_DEBUG") != NULL)
#ifdef __GLIBC__
fprintf(stderr, "libfaketime: forced monotonic fix for %s = %s (glibc version %s)\n",
function_name, result ? "yes":"no", glibc_version_string);
#else
fprintf(stderr, "libfaketime: forced monotonic fix for %s = %s (not glibc-compiled)\n",
function_name, result ? "yes":"no");
#endif
return result;
}
int pthread_cond_timedwait_common(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime, ft_lib_compat_pthread compat)
{
@@ -3628,8 +3689,14 @@ int pthread_cond_timedwait_common(pthread_cond_t *cond, pthread_mutex_t *mutex,
CLOCK_MONOTONIC. */
#ifndef __ARM_ARCH
#ifndef FORCE_MONOTONIC_FIX
if (clk_id == CLOCK_MONOTONIC)
timespecadd(&faketime, &tdiff_actual, &tp);
if (clk_id == CLOCK_MONOTONIC) {
if (needs_forced_monotonic_fix("pthread_cond_timedwait") == true) {
timespecadd(&realtime, &tdiff_actual, &tp);
}
else {
timespecadd(&faketime, &tdiff_actual, &tp);
}
}
else
#endif
#endif

View File

@@ -98,7 +98,8 @@ void* pthread_test(void* args)
timeToWait.tv_nsec = now.tv_nsec;
printf("pthread_cond_timedwait: CLOCK_MONOTONIC test\n");
printf("(Intentionally sleeping 1 second..., see docs about CLOCK_MONOTONIC test)\n");
printf("(Intentionally sleeping 1 second...)\n");
printf("(If this test hangs for more than a few seconds, please report\n your glibc version and system details as FORCE_MONOTONIC_FIX\n issue at https://github.com/wolfcw/libfaketime)\n");
fflush(stdout);
pthread_mutex_lock(&fakeMutex);