mirror of
https://github.com/wolfcw/libfaketime.git
synced 2026-05-24 12:16:06 +03:00
Compare commits
1 Commits
v0.9.11
...
pthread_co
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
46a0f84c1e |
2
.github/workflows/make-test.yml
vendored
2
.github/workflows/make-test.yml
vendored
@@ -12,7 +12,7 @@ jobs:
|
||||
build:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, ubuntu-22.04]
|
||||
os: [ubuntu-latest, macOS-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
steps:
|
||||
|
||||
19
Makefile
19
Makefile
@@ -33,23 +33,4 @@ distclean:
|
||||
$(MAKE) $(SELECTOR) -C src distclean
|
||||
$(MAKE) $(SELECTOR) -C test distclean
|
||||
|
||||
macarm64:
|
||||
$(MAKE) $(SELECTOR) -C src clean
|
||||
$(MAKE) $(SELECTOR) -C src distclean
|
||||
$(MAKE) $(SELECTOR) -C src all
|
||||
# $(MAKE) $(SELECTOR) -C test all
|
||||
# $(MAKE) $(SELECTOR) -C test distclean
|
||||
$(MAKE) $(SELECTOR) -C src install
|
||||
$(MAKE) $(SELECTOR) -C man install
|
||||
$(INSTALL) -dm0755 "${DESTDIR}${PREFIX}/share/doc/faketime/"
|
||||
$(INSTALL) -m0644 README "${DESTDIR}${PREFIX}/share/doc/faketime/README"
|
||||
$(INSTALL) -m0644 NEWS "${DESTDIR}${PREFIX}/share/doc/faketime/NEWS"
|
||||
|
||||
macarm64full:
|
||||
$(MAKE) $(SELECTOR) -C src clean
|
||||
$(MAKE) $(SELECTOR) -C src distclean
|
||||
$(MAKE) $(SELECTOR) -C src all
|
||||
$(MAKE) $(SELECTOR) -C test all
|
||||
# $(MAKE) $(SELECTOR) -C test distclean
|
||||
|
||||
.PHONY: all test install uninstall clean distclean
|
||||
|
||||
13
NEWS
13
NEWS
@@ -1,17 +1,4 @@
|
||||
Since 0.9.10:
|
||||
- Fixed various cross-platform compile-time issues
|
||||
- Honor nanosecond parameters/fields in relevant system calls
|
||||
- Limited improvements to enhance compatibility with other
|
||||
LD_PRELOAD libraries
|
||||
- Added selected more intercepted system calls
|
||||
- Unset FAKETIME_SHARED automatically for child processes
|
||||
when enabling FAKETIME_FLSHM=1
|
||||
- Disable shared memory for child processes through
|
||||
FAKETIME_DISABLE_SHM=1
|
||||
|
||||
Since 0.9.9:
|
||||
- automatically try to decide about FORCE_MONOTONIC_FIX
|
||||
at run-time when not set as a compile-time flag
|
||||
- improved macOS Monterey support through dyld interposing
|
||||
- changed interception hooks for stat() and similar functions,
|
||||
refactored to use a common handler (@sirainen)
|
||||
|
||||
29
README
29
README
@@ -1,5 +1,5 @@
|
||||
libfaketime, version 0.9.11 (May 2025)
|
||||
======================================
|
||||
libfaketime, version 0.9.10 (February 2022)
|
||||
===========================================
|
||||
|
||||
|
||||
Content of this file:
|
||||
@@ -103,28 +103,6 @@ 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
|
||||
---------------
|
||||
@@ -486,9 +464,6 @@ for long-running systems (servers with high uptime) and systems on which
|
||||
a lot of processes are started (e.g., servers handling many containers
|
||||
or similar virtualization mechanisms).
|
||||
|
||||
Use of shared memory can be disabled by setting the FAKETIME_DISABLE_SHM
|
||||
environment variable, or equivalently, passing --disable-shm to faketime.
|
||||
|
||||
|
||||
Intercepting time-setting calls
|
||||
-------------------------------
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.TH FAKETIME "1" "May 2025" "faketime 0.9.11" wolfcw
|
||||
.TH FAKETIME "1" "February 2022" "faketime 0.9.10" wolfcw
|
||||
.SH NAME
|
||||
faketime \- manipulate the system time for a given command
|
||||
.SH SYNOPSIS
|
||||
@@ -32,9 +32,6 @@ use the advanced timestamp specification format.
|
||||
\fB\--exclude-monotonic\fR
|
||||
Do not fake time when the program makes a call to clock_gettime with a CLOCK_MONOTONIC clock.
|
||||
.TP
|
||||
\fB\--disable-shm\fR
|
||||
Disable use of shared memory by libfaketime.
|
||||
.TP
|
||||
\fB\--date-prog <PATH>\fR
|
||||
Use a specific GNU-date compatible implementation of the helper used to transform "timestamp format" strings into programmatically usable dates, instead of a compile-time default guess for the generic target platform.
|
||||
|
||||
|
||||
29
src/Makefile
29
src/Makefile
@@ -84,11 +84,6 @@
|
||||
# - avoid that the faketime wrapper complains when running within a
|
||||
# libfaketime environment
|
||||
#
|
||||
# FAIL_PRE_INIT_CALLS
|
||||
# - If the time is queried before the library was initialised, let the
|
||||
# call fail instead of trying to initialise on-the-fly. This fixes /
|
||||
# works around hangs that were seen with address sanitizer.
|
||||
#
|
||||
# * Compilation addition: second libMT target added for building the pthread-
|
||||
# enabled library as a separate library
|
||||
#
|
||||
@@ -115,36 +110,20 @@ PREFIX ?= /usr/local
|
||||
LIBDIRNAME ?= /lib/faketime
|
||||
PLATFORM ?=$(shell uname)
|
||||
|
||||
ifeq ($(shell $(CC) -v 2>&1 | grep -c "clang version"), 1)
|
||||
COMPILER := clang
|
||||
else
|
||||
COMPILER := gcc
|
||||
endif
|
||||
export COMPILER
|
||||
|
||||
CFLAGS += -std=gnu99 -Wall -Wextra -Werror -DFAKE_PTHREAD -DFAKE_STAT -DFAKE_UTIME -DFAKE_SLEEP -DFAKE_TIMERS -DFAKE_INTERNAL_CALLS -fPIC -DPREFIX='"'$(PREFIX)'"' -DLIBDIRNAME='"'$(LIBDIRNAME)'"' $(FAKETIME_COMPILE_CFLAGS)
|
||||
|
||||
ifeq ($(COMPILER),clang)
|
||||
CFLAGS += -Wno-tautological-pointer-compare
|
||||
endif
|
||||
|
||||
ifeq ($(COMPILER),gcc)
|
||||
CFLAGS += -Wno-nonnull-compare
|
||||
endif
|
||||
|
||||
CFLAGS += -std=gnu99 -Wall -Wextra -Werror -Wno-nonnull-compare -DFAKE_PTHREAD -DFAKE_STAT -DFAKE_UTIME -DFAKE_SLEEP -DFAKE_TIMERS -DFAKE_INTERNAL_CALLS -fPIC -DPREFIX='"'$(PREFIX)'"' -DLIBDIRNAME='"'$(LIBDIRNAME)'"' $(FAKETIME_COMPILE_CFLAGS)
|
||||
ifeq ($(PLATFORM),SunOS)
|
||||
CFLAGS += -D__EXTENSIONS__ -D_XOPEN_SOURCE=600
|
||||
endif
|
||||
|
||||
LIB_LDFLAGS += -shared
|
||||
|
||||
LDFLAGS += $(FAKETIME_LINK_FLAGS)
|
||||
LDFLAGS += $(FAKETIME_LINK_FLAGS) -lpthread
|
||||
ifneq ($(PLATFORM),SunOS)
|
||||
LDFLAGS += -Wl,--version-script=libfaketime.map
|
||||
endif
|
||||
|
||||
LDADD += -ldl -lm -lrt -lpthread
|
||||
BIN_LDFLAGS += -lrt -lpthread
|
||||
LDADD += -ldl -lm -lrt
|
||||
BIN_LDFLAGS += -lrt
|
||||
|
||||
SRC = libfaketime.c
|
||||
LIBS_OBJ = libfaketime.o libfaketimeMT.o
|
||||
|
||||
@@ -56,22 +56,7 @@ INSTALL ?= install
|
||||
PREFIX ?= /usr/local
|
||||
|
||||
CFLAGS += -DFAKE_SLEEP -DFAKE_INTERNAL_CALLS -DPREFIX='"'${PREFIX}'"' $(FAKETIME_COMPILE_CFLAGS) -DMACOS_DYLD_INTERPOSE -DFAKE_SETTIME
|
||||
LIB_LDFLAGS += -dynamiclib -current_version 0.9.11 -compatibility_version 0.7
|
||||
|
||||
# ARM64 MacOS (M1/M2/M3/Apple Silicon/etc) processors require a target set as their current version, or they
|
||||
# will receive the following error:
|
||||
# dyld[6675]: terminating because inserted dylib '/usr/local/lib/faketime/libfaketime.1.dylib' could not be loaded: tried: '/usr/local/lib/faketime/libfaketime.1.dylib' (mach-o file, but is an incompatible architecture (have 'arm64', need 'arm64e')), '/System/Volumes/Preboot/Cryptexes/OS/usr/local/lib/faketime/libfaketime.1.dylib' (no such file), '/usr/local/lib/faketime/libfaketime.1.dylib' (mach-o file, but is an incompatible architecture (have 'arm64', need 'arm64e'))
|
||||
# dyld[6675]: tried: '/usr/local/lib/faketime/libfaketime.1.dylib' (mach-o file, but is an incompatible architecture (have 'arm64', need 'arm64e')), '/System/Volumes/Preboot/Cryptexes/OS/usr/local/lib/faketime/libfaketime.1.dylib' (no such file), '/usr/local/lib/faketime/libfaketime.1.dylib' (mach-o file, but is an incompatible architecture (have 'arm64', need 'arm64e'))
|
||||
# Outputs `arm64` on ARM64
|
||||
OS := $(shell uname -m)
|
||||
# Outputs a number, eg 14.4 for MacOS Sonoma 14.4
|
||||
MACOS_PRODUCT_VERSION := $(shell sw_vers --productVersion | cut -d. -f1,2)
|
||||
|
||||
# Check if arm64 is in OS, if so, add the target
|
||||
ifeq ($(OS),arm64)
|
||||
CFLAGS += -target arm64e-apple-macos$(MACOS_PRODUCT_VERSION)
|
||||
LIB_LDFLAGS += -target arm64e-apple-macos$(MACOS_PRODUCT_VERSION)
|
||||
endif
|
||||
LIB_LDFLAGS += -dynamiclib -current_version 0.9.10 -compatibility_version 0.7
|
||||
|
||||
SONAME = 1
|
||||
LIBS = libfaketime.${SONAME}.dylib
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* libfaketime wrapper command
|
||||
*
|
||||
* This file is part of libfaketime, version 0.9.11
|
||||
* This file is part of libfaketime, version 0.9.10
|
||||
*
|
||||
* libfaketime is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License v2 as published by the
|
||||
@@ -48,7 +48,7 @@
|
||||
|
||||
#include "faketime_common.h"
|
||||
|
||||
const char version[] = "0.9.11";
|
||||
const char version[] = "0.9.10";
|
||||
|
||||
#if (defined __APPLE__) || (defined __sun)
|
||||
static const char *date_cmd = "gdate";
|
||||
@@ -77,9 +77,6 @@ void usage(const char *name)
|
||||
" --exclude-monotonic : Prevent monotonic clock from drifting (not the raw monotonic one)\n"
|
||||
#ifdef FAKE_PID
|
||||
" -p PID : Pretend that the program's process ID is PID\n"
|
||||
#endif
|
||||
#ifndef FAKE_STATELESS
|
||||
" --disable-shm : Disable use of shared memory by libfaketime.\n"
|
||||
#endif
|
||||
" --date-prog PROG : Use specified GNU-compatible implementation of 'date' program\n"
|
||||
"\n"
|
||||
@@ -153,14 +150,6 @@ int main (int argc, char **argv)
|
||||
curr_opt++;
|
||||
continue;
|
||||
}
|
||||
#ifndef FAKE_STATELESS
|
||||
else if (0 == strcmp(argv[curr_opt], "--disable-shm"))
|
||||
{
|
||||
setenv("FAKETIME_DISABLE_SHM", "1", true);
|
||||
curr_opt++;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
else if (0 == strcmp(argv[curr_opt], "--date-prog"))
|
||||
{
|
||||
curr_opt++;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,21 +1,18 @@
|
||||
CC = gcc
|
||||
|
||||
CFLAGS += -std=gnu99 -Wall -DFAKE_STAT -Werror -Wextra $(FAKETIME_COMPILE_CFLAGS) -U_FILE_OFFSET_BITS -U_TIME_BITS
|
||||
CFLAGS += -std=gnu99 -Wall -DFAKE_STAT -Werror -Wextra $(FAKETIME_COMPILE_CFLAGS)
|
||||
LDFLAGS += -lrt -lpthread
|
||||
|
||||
SRC = timetest.c
|
||||
OBJ = ${SRC:.c=.o}
|
||||
|
||||
TEST_SNIPPETS = $(notdir $(basename $(wildcard snippets/*.c)))
|
||||
EXPECTATIONS = $(notdir $(basename $(wildcard snippets/*.variable)))
|
||||
EXPECTATIONS= $(notdir $(basename $(wildcard snippets/*.variable)))
|
||||
|
||||
ALL_TESTS = timetest test
|
||||
|
||||
ifneq ($(filter -DINTERCEPT_SYSCALL,${CFLAGS}),)
|
||||
ALL_TESTS += confirm_variadic_promotion
|
||||
else
|
||||
TEST_SNIPPETS := $(filter-out syscall%,${TEST_SNIPPETS})
|
||||
EXPECTATIONS := $(filter-out syscall%,${EXPECTATIONS})
|
||||
endif
|
||||
|
||||
all: $(ALL_TESTS)
|
||||
@@ -26,7 +23,7 @@ all: $(ALL_TESTS)
|
||||
timetest: ${OBJ}
|
||||
${CC} -o $@ ${OBJ} ${LDFLAGS}
|
||||
|
||||
test: timetest functest libmallocintercept.so
|
||||
test: timetest functest
|
||||
@echo
|
||||
@./test.sh
|
||||
|
||||
@@ -40,9 +37,6 @@ functest:
|
||||
randomtest: repeat_random
|
||||
./randomtest.sh
|
||||
|
||||
libmallocintercept.so: libmallocintercept.c
|
||||
${CC} -shared -o $@ -fpic ${CFLAGS} $<
|
||||
|
||||
# ensure our variadic argument unpacking/repacking works as expected
|
||||
confirm_variadic_promotion: variadic_promotion
|
||||
./variadic_promotion
|
||||
@@ -76,7 +70,7 @@ use_lib_%: _use_lib_test.c snippets/%.c lib%.so
|
||||
## cleanup and metainformation
|
||||
|
||||
clean:
|
||||
@rm -f ${OBJ} timetest getrandom_test syscall_test $(foreach f,${TEST_SNIPPETS},use_lib_${f} lib${f}.so run_${f}) variadic_promotion variadic/*.o repeat_random libmallocintercept.so
|
||||
@rm -f ${OBJ} timetest getrandom_test syscall_test $(foreach f,${TEST_SNIPPETS},use_lib_${f} lib${f}.so run_${f}) variadic_promotion variadic/*.o
|
||||
|
||||
distclean: clean
|
||||
@echo
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 be.storaged GmbH
|
||||
*
|
||||
* This file is part of libfaketime
|
||||
*
|
||||
* libfaketime is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License v2 as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* libfaketime is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License v2 along
|
||||
* with the libfaketime; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static void print_msg(const char *msg) {
|
||||
size_t out;
|
||||
out = write(0, msg, strlen(msg));
|
||||
(void) out; /* unused */
|
||||
}
|
||||
|
||||
static void* actual_malloc(size_t size) {
|
||||
/* We would like to use "the real malloc", but cannot. Thus, this
|
||||
* implements a trivial, allocate-only bump allocator to make things
|
||||
* work.
|
||||
*/
|
||||
static char memory_arena[16 << 20];
|
||||
static size_t allocated_index = 0;
|
||||
|
||||
void *result = &memory_arena[allocated_index];
|
||||
|
||||
allocated_index += size;
|
||||
/* align to a multiple of 8 bytes */
|
||||
allocated_index = (allocated_index + 7) / 8 * 8;
|
||||
|
||||
if (allocated_index >= sizeof(memory_arena)) {
|
||||
print_msg("libmallocintercept is out of memory!");
|
||||
abort();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void poke_faketime(void) {
|
||||
#ifdef FAIL_PRE_INIT_CALLS
|
||||
/* To complicate things for libfaketime, this calls clock_gettime()
|
||||
* while holding a lock. This should simulate problems that occurred
|
||||
* with address sanitizer.
|
||||
*/
|
||||
static pthread_mutex_t time_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
struct timespec timespec;
|
||||
|
||||
pthread_mutex_lock(&time_mutex);
|
||||
clock_gettime(CLOCK_REALTIME, ×pec);
|
||||
pthread_mutex_unlock(&time_mutex);
|
||||
#else
|
||||
print_msg("FAIL_PRE_INIT_CALLS not defined, skipping poke_faketime() ");
|
||||
#endif
|
||||
}
|
||||
|
||||
void *malloc(size_t size) {
|
||||
print_msg("Called malloc() from libmallocintercept...");
|
||||
poke_faketime();
|
||||
print_msg("successfully\n");
|
||||
return actual_malloc(size);
|
||||
}
|
||||
|
||||
void free(void *ptr) {
|
||||
long int ptr2 = (long int) ptr; ptr2 -= (long int) ptr;
|
||||
print_msg("Called free() on from libmallocintercept...");
|
||||
poke_faketime();
|
||||
print_msg("successfully\n");
|
||||
|
||||
/* We cannot actually free memory */
|
||||
}
|
||||
@@ -1,2 +1,2 @@
|
||||
time_t t = time(NULL);
|
||||
printf("[%s] time() yielded %lu\n", where, (unsigned long)t);
|
||||
printf("[%s] time() yielded %zd\n", where, t);
|
||||
|
||||
19
test/test.sh
19
test/test.sh
@@ -1,7 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
FTPL="${FAKETIME_TESTLIB:-../src/libfaketime.so.1}"
|
||||
MALLOC_INTERCEPT=./libmallocintercept.so
|
||||
|
||||
if [ -f /etc/faketimerc ] ; then
|
||||
echo "Running the test program with your system-wide default in /etc/faketimerc"
|
||||
@@ -63,24 +62,6 @@ echo "\$ LD_PRELOAD=$FTPL FAKETIME=\"-15d\" date"
|
||||
LD_PRELOAD="$FTPL" FAKETIME="-15d" date
|
||||
echo
|
||||
|
||||
echo "============================================================================="
|
||||
echo
|
||||
|
||||
echo "Running the test program with malloc interception"
|
||||
echo "\$ LD_PRELOAD=./libmallocintercept.so:$FTPL ./timetest"
|
||||
LD_PRELOAD="./libmallocintercept.so:$FTPL" ./timetest
|
||||
echo
|
||||
|
||||
echo "============================================================================="
|
||||
echo
|
||||
|
||||
echo "@2005-03-29 14:14:14" > .faketimerc-for-test
|
||||
echo "Running the test program with malloc interception and file faketimerc"
|
||||
echo "\$ FAKETIME_NO_CACHE=1 FAKETIME_TIMESTAMP_FILE=.faketimerc-for-test LD_PRELOAD=./libmallocintercept.so:$FTPL ./timetest"
|
||||
FAKETIME_NO_CACHE=1 FAKETIME_TIMESTAMP_FILE=.faketimerc-for-test LD_PRELOAD="./libmallocintercept.so:$FTPL" ./timetest
|
||||
rm .faketimerc-for-test
|
||||
echo
|
||||
|
||||
echo "============================================================================="
|
||||
echo "Testing finished."
|
||||
|
||||
|
||||
@@ -98,8 +98,7 @@ void* pthread_test(void* args)
|
||||
timeToWait.tv_nsec = now.tv_nsec;
|
||||
|
||||
printf("pthread_cond_timedwait: 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");
|
||||
printf("(Intentionally sleeping 1 second..., see docs about CLOCK_MONOTONIC test)\n");
|
||||
fflush(stdout);
|
||||
|
||||
pthread_mutex_lock(&fakeMutex);
|
||||
|
||||
Reference in New Issue
Block a user