Skip to content

Commit 44215b6

Browse files
committed
Add support for FAKETIME_KEEP_BEFORE_NSEC_SINCE_EPOCH
`FAKETIME_KEEP_BEFORE_NSEC_SINCE_EPOCH` behaves similar to `FAKETIME_START_AFTER_SECONDS`, with two main differences: * the timestamp is absolute, instead of being relative to process startup * the timestamp is specified in nanoseconds The reason we want this feature is the following use case. We run a large test suite under faketime. That test suite has access to filesystem artifacts that were created prior to test start up. Among those artifacts are some caches which are considered up to date iff the timestamps of the files match what's recorded in a data structure. This means that to access those caches to be considered valid we need their timestamps to not be rewritten. The reason we can't use `FAKETIME_START_AFTER_SECONDS` directly is that the test suite consists of multiple processes, for those processes to correctly interact with each other they need a consistent timestamp mapping that is shared between them. In fact the simplest bash script already behaves incorrectly because the commands use different process start times. ``` touch old FAKETIME=+100d FAKETIME_START_AFTER_SECONDS=0 bash -c 'touch new; stat old new' ``` The expected behavior is that the timestamp of `old` is not rewritten, while the timestamp of `new` is rewritten. That is in fact achievable now: ``` touch old now_ns=$(date +%s.%N | sed -r 's_\.__') FAKETIME=+100d FAKETIME_KEEP_BEFORE_NSEC_SINCE_EPOCH="$now_ns" bash -c 'touch new; stat old new' ```
1 parent 942b30e commit 44215b6

File tree

1 file changed

+15
-1
lines changed

1 file changed

+15
-1
lines changed

src/libfaketime.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,9 @@ static int outfile = -1;
340340

341341
static bool limited_faking = false;
342342
static long callcounter = 0;
343+
344+
static long long ft_keep_before_nsec_since_epoch = -1;
345+
343346
static long ft_start_after_secs = -1;
344347
static long ft_stop_after_secs = -1;
345348
static long ft_start_after_ncalls = -1;
@@ -2897,6 +2900,11 @@ static void ftpl_really_init(void)
28972900
}
28982901
}
28992902

2903+
if ((tmp_env = getenv("FAKETIME_KEEP_BEFORE_NSEC_SINCE_EPOCH")) != NULL)
2904+
{
2905+
ft_keep_before_nsec_since_epoch = atoll(tmp_env);
2906+
limited_faking = true;
2907+
}
29002908
if ((tmp_env = getenv("FAKETIME_START_AFTER_SECONDS")) != NULL)
29012909
{
29022910
ft_start_after_secs = atol(tmp_env);
@@ -3220,9 +3228,15 @@ int fake_clock_gettime(clockid_t clk_id, struct timespec *tp)
32203228
timespecsub(tp, &ftpl_starttime.real, &tmp_ts);
32213229
break;
32223230
}
3223-
32243231
if (limited_faking)
32253232
{
3233+
if (ft_keep_before_nsec_since_epoch != -1) {
3234+
long long tp_nsec = ((long long)tp->tv_sec) * 1000000000 + ((long long)tp->tv_nsec);
3235+
if (tp_nsec < ft_keep_before_nsec_since_epoch) {
3236+
ret = 0;
3237+
goto abort;
3238+
}
3239+
}
32263240
/* Check whether we actually should be faking the returned timestamp. */
32273241
/* fprintf(stderr, "(libfaketime limits -> runtime: %lu, callcounter: %lu\n", (*time_tptr - ftpl_starttime), callcounter); */
32283242
if (((ft_start_after_secs != -1) && (tmp_ts.tv_sec < ft_start_after_secs))

0 commit comments

Comments
 (0)