An experimental library for realtime control of the speed of time in Linux child processes
Project description
Libtimecontrol lets you control the rate at which time runs in a Linux child process. Note: This is an experimental library with some known issues (see "known issues" for details.)
Installation
$ pip install libtimecontrol
Usage
import os
import subprocess
from libtimecontrol import TimeController
controller = TimeController()
# Make time run 25x faster in child processes.
controller.set_speedup(25)
# Launch a time controlled child process.
# Due to limitations on time controlling, the watch interval and date output aren't
# affected by the time control. However watch's process time is correctly time
# controlled which can be seen by how quickly watch's printed time, seen in the top
# right corner of its output, is moving.
env = os.environ
subprocess.run(
["watch", "-n1", "date"],
env=env | controller.child_flags(),
)
How it works
We use LD_PRELOAD to override the libc time functions with custom ones that read virtual
clocks. The virtual clocks are initialized to match the system's real clocks when a
program loads. After that, the virtual clocks advance relative to the real clock by
the value of the last set_speed's speedup value, starting with a speedup of 1.
Known Issues
Noise in your stdout
Preloading the 32-bit and 64-bit time control libraries at the same time will dump "ERROR: ld.so: object '.../libtime_control32_dlsym.so' from LD_PRELOAD cannot be preloaded (wrong ELF class: ELFCLASS32): ignored." errors to the console. These can safely be ignored, but they do add noise to your logs.
Multiple Dlsym Overrides in LD_PRELOAD
When running in the DLSYM preload mode, this library may be ignored if other libraries in your LD_PRELOAD are also performing dlsym-based overrides. If you encounter this error, try putting this library's preloads in front of any other LD_PRELOAD libraries, as I've tried to make this library correctly invoke the next dlsym in the preload chain, when there is one.
Edge Cases
There are a few cases where the time control behavior isn't quite correct. I don't plan on implementing fixes or reviewing/accepting pull requests for these, but do feel free to fork the project if you want to fix these things.
-
Per-process virtual clocks can be skewed relative to each other, since each process's virtual clock starts at the real-clock's time when a time controlled process launches. This could be fixed by storing the virtual clock in across processes in shared memory.
-
Each sleep's duration is calculated at sleep time and any calls to
set_speedupdon't update any ongoing sleep's duration. This means if you callset_speedup(.01)andsleep(1), the thread will sleep for 100 seconds, even if you callset_speedup(2)a second after thesleepcall. This could be fixed by making the sleep implementation listen for speedup changes. -
No timeout parameters in libc are affected by the time control. This means a call like
select(..., /*timeout=*/one_sec)will run with a one second timeout regardless of the set speedup. This is why for examplewatch's watch interval is unaffected by the time control, it uses a select timeout for timing itself. One could update this library so that it adjusts all of the timeouts, but it's not clear that that wouldn't affect programs' stability.
Related Projects
Libfaketime is another project that fakes a processes time. It's more mature, but isn't as focused on realtime time control.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file libtimecontrol-0.2.0-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl.
File metadata
- Download URL: libtimecontrol-0.2.0-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
- Upload date:
- Size: 274.7 kB
- Tags: Python 3, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.11.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1cf0146dd1762596502baa913b2a66d446b372ad3e0a42969ea56283c85546b3
|
|
| MD5 |
4bded73298c151540f96fd5ed3df5131
|
|
| BLAKE2b-256 |
607bc8022fd0aa777e038f16c69b80ae5cbfa528a98ea2c8349871cf4049c911
|