wolfcw / libfaketime

libfaketime modifies the system time for a single application
https://github.com/wolfcw/libfaketime
GNU General Public License v2.0
2.71k stars 325 forks source link

Monotonic timerfd not skipped even if env var is set #378

Open sveyret opened 2 years ago

sveyret commented 2 years ago

Hi! I have an app using timerfd_create, timerfd_settime and timerfd_gettime with monotonic clock id. Because I don’t want to fake monotonic timers, I have set FAKETIME_DONT_FAKE_MONOTONIC=1. The problem is that the type of timer is not detected and faked anyway, which makes my app wait for a very long time if the clock is set in the past, and even throw an exception if it is set in the future (it tries to wait for a negative amount of time). If there is no cleaner way to do it, it would be good to have at least an environment variable to deactivate timerfd (and only timerfd) faking. Thank you.

wolfcw commented 2 years ago

The problem seems to be that the parameters of timerfd_settime and timerfd_gettime, unlike the ones of timerfd_create (which is not intercepted by libfaketime), give no indication about which clockid is used for the timer. There also seems to be no other function (at least in the man pages) to determine the clockid based on a given fd.

Disabling timerfd-related faking would therefore also disable it for other clockids, which is not something to expect solely based on DONT_FAKE_MONOTONIC set.

As a fix for your specific case, you simply can rename the intercepted functions:

https://github.com/wolfcw/libfaketime/blob/0ca35dd8c4532075d6805133a8f2f319f54c26ff/src/libfaketime.c#L2095

https://github.com/wolfcw/libfaketime/blob/0ca35dd8c4532075d6805133a8f2f319f54c26ff/src/libfaketime.c#L2117

which effectively disables their interception. A cleaner fix probably would involve intercepting timerfd_create as well and keeping track of which fds correspond to which clockid libfaketime-internally. This sort of internal tracking across different function calls is actually something we never did before to keep things simple, but might be necessary here.

sveyret commented 2 years ago

Thank you for your answer, @wolfcw . Actually, I discovered in my app that I also use some real clock based timerfd, so, contrary to what I said previously, totally disabling them is not possible. I made a patch which is reading the file /proc/self/fdinfo/fd, but it is not very reliable as it requires CONFIG_PROC_FS to be set in the kernel (which is generally the case) and depends on the way clockid is displayed. Intercepting timerfd_create and tracking clockid matching with fd as you suggest is probably the cleanest solution.