• Stars
    star
    819
  • Rank 55,659 (Top 2 %)
  • Language
    C
  • License
    MIT License
  • Created almost 12 years ago
  • Updated about 5 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

The engine that powers DeLorean!

Build Status

Fluxcapacitor

Fluxcapacitor is a tool for making your program run without blocking on timeouts, on functions like poll and select, by spoofing POSIX time functions.

It is somewhat similar to:

While these tools patch time libraries in Ruby and Python, fluxcapacitor works on a lower layer by "patching" low-level syscalls. That way, it can lie about time to any program in any programming language, as long as it runs on Linux.

This approach has a significant advantage: it is possible to lie about time to many processes at the same time. It is especially useful for running network applications where server and client run in different processes which rely on time. It will also work with multithreaded applications.

Another comparable project is:

Fluxcapacitor is fundamentally different from libfaketime, which can fake the time functions, but doesn't affect the runtime of the program. Conversely, fluxcapacitor will make your program run faster and be 100% CPU constrained. It does that by "speeding up" blocking syscalls. Faking time is a necessary side effect.

Internally,Fluxcapacitor uses ptrace on syscalls and LD_PRELOAD, which is why it's Linux specific.

Join the fluxcapacitor-dev mailing list. Or view the archives.

Basic examples

When you run sleep bash command, well, it will block the console for a given time. For example:

$ sleep 12

will halt terminal for 12 seconds. When you run it with fluxcapacitor:

$ ./fluxcapacitor -- sleep 12

it will finish instantly. Cool, huh? To illustrate this:

$ time sleep 12
real    0m12.003s

while:

$ time ./fluxcapacitor -- sleep 12
real    0m0.057s

Another example, take a look at this session:

$ date
Thu Feb 14 23:49:55 GMT 2013
$ ./fluxcapacitor -- bash -c "date; sleep 120; date"
Thu Feb 14 23:49:57 GMT 2013
Thu Feb 14 23:51:57 GMT 2013
$ date
Thu Feb 14 23:49:58 GMT 2013

You should see a program thinks time had passed, although it did not in reality.

Ever heard of the year 2038 problem? Here's how it's going to look like in action (this works on 32 bit systems):

$ ./fluxcapacitor -- bash -c "sleep 700000000; date"
Thu Apr 26 17:44:25 BST 2035
$ ./fluxcapacitor -- bash -c "sleep 800000000; date"
Wed May 21 20:04:03 GMT 1902

Finally, fluxcapacitor works with any programming language:

$ ./fluxcapacitor -- python2 -c "import time; time.sleep(1000)"

For reference, fluxcapacitor usage info:

$ ./fluxcapacitor --help
Usage:

    fluxcapacitor [options] [ -- command [ arguments ... ] ... ]

Options:

  --libpath=PATH       Load fluxcapacitor_preload.so from
                       selected PATH directory.
  --signal=SIGNAL      Use specified signal to interrupt blocking
                       syscall instead of SIGURG.
  --verbose,-v         Print more stuff.
  --help               Print this message.

How does it work

Fluxcapacitor internally does two things:

  1. It forces fluxcapacitor_preload.so to be preloaded using the LD_PRELOAD linux facility. This library is responsible for two things:

    • It makes sure that clock_gettime() will use the standard syscall, not the ultra-fast VDSO mechanism. That gives us the opportunity to replace the return value of the system call later.
    • It replaces various time-related libc functions: clock_gettime(), gettimeofday(), time(), ftime(), nanosleep() and clock_nanosleep() with variants using modified clock_gettime(). That simplifies syscall semantics thus making some parts of the server code less involved.
  2. It runs then given command and its forked children in a ptrace() sandbox, capturing all syscalls. Some syscalls - notably clock_gettime, have their original results returned from the kernel overwritten by faked values. Other syscalls, like select(), poll() andepoll_wait(), can be interrupted (by a signal) and the result will be set to look like a timeout has expired. Full list of recognized syscalls that can be sped up:

    • epoll_wait(), epoll_pwait()
    • select(), _newselect(), pselect6()
    • poll(), ppoll()
    • nanosleep()

Speeding up

Fluxcapacitor monitors all syscalls run by the child processes. All syscalls are relayed to the kernel, as normal. This operation continues until fluxcapacitor notices that all the child processes are waiting on recognised time-related syscalls, like poll or select. When that happens, fluxcapacitor decides to speed up the time. It advances the internal timer and sends a signal (SIGURG by default) to the process that is blocked with the smallest timeout value. Fluxcapacitor is then woken up by the kernel to give it a chance to pass the signal to the child. It swallows the signal and sets the return value of the syscall to look like a timeout had expired. See diagram:

  child          fluxcapacitor              kernel
  -----          -------------              ------

   |
   +--- select(1s) -->+
                      |
                      +------------------------>

                      kill(child, SIGURG)

                      +<---- signal received ---
                      |
                      (pretend it was a timeout)
                      |
   +<--- timeout -----+
   |

When it won't work

Fluxcapacitor won't work in a number of cases:

  1. If your code is statically compiled and fluxcapacitor_preload.so ld-preloaded library can't play its role.

  2. If your code uses unpopular blocking functions in the event loop, like signalfd() and sigwait(), or if your program relies heavily on signals and things like alert(), setitimer(), or timerfd_create().

  3. If your code uses file access or modification timestamps. Fluxcapacitor does not mock that.

Basically, for Fluxcapacitor to work all the time, queries need to be done using gettimeofday() or clock_gettime(), and all the waiting for timeouts must rely on select(), poll() or epoll_wait(). Fortunately, that's the case in most programming languages.

Advanced usage

Fluxcapacitor's main application is speeding up tests.

Say you have a "delayed echo" server and you want to test it. It echos messages, just delayed by a few seconds. You don't want your tests to take too long. For example the code:

Normally you could run the server, run the tests in a separate console and wait for some time. With fluxcapacitor you write a wrapper program:

#!/usr/bin/env python2

import os
import time
import signal

server_pid = os.fork()
if server_pid == 0:
    os.execv("/usr/bin/python2", ["python2", "server.py"])
    os._exit(0)
else:
    time.sleep(1)
    os.system("python2 tests.py")
    os.kill(server_pid, signal.SIGINT)

This script just runs the tests in an automated manner. Normally the tests take 1 second each:

$ time python2 run_test.py
real    0m5.112s

With fluxcapacitor it's much faster:

$ ./fluxcapacitor -- python2 run_test.py
real    0m0.355s

Development

Prerequisites

To compile the things you need are git, gcc and make. This should do:

$ sudo yum git gcc make

or

$ sudo apt-get install git gcc make

Building

To compile fluxcapacitor you need a reasonably recent linux distribution. Type:

make build

Testing

Fluxcapacitor comes with a number of python tests. See tests subdirectory for details. To test fluxcapacitor type:

make test

or just:

make

You can also run specific tests, but that's a bit more complex. For example to run SingleProcess.test_bash_sleep from tests/tests_basic.py:

FCPATH="$PWD/fluxcapacitor --libpath=$PWD" \
    python2 tests/tests_basic.py SingleProcess.test_bash_sleep

More Repositories

1

dump

Unfinished projects and snippets
PHP
485
star
2

openonload

git import of openonload.org https://gist.github.com/majek/ae188ae72e63470652c9
C
228
star
3

puka

Puka - the opinionated RabbitMQ client
Python
180
star
4

lua-channels

Go style channels in pure Lua
Lua
139
star
5

goplayground

Go
55
star
6

csiphash

SipHash in C
C
47
star
7

pysiphash

SipHash in Python
Python
38
star
8

inet-tool

inet-tool - the manager for BPF_PROG_TYPE_INET_LOOKUP eBPF programs
C
25
star
9

ixgbe

git clone of intel-wired-lan ixgbe drivers https://gist.github.com/majek/9d4910c24ccbbe237025
C
19
star
10

libtask

Shameless copy of http://swtch.com/libtask/ and/or http://code.google.com/p/libtask/
C
16
star
11

rats

A clone of NATS using RabbitMQ.
Ruby
11
star
12

baby-steps-in-assembly

Assembly
8
star
13

vx32example

Simplistic example of vx32 lib usage
C
8
star
14

sockjs-client

Repo migrated: https://github.com/sockjs/sockjs-client
8
star
15

django-sockjs

Simplistic example of SockJS-tornado used with Django
Python
7
star
16

mmuniq

Streaming tool to filter out duplicate lines. "uniq" implemented with bloom filter.
C
7
star
17

avs

Advanced Visualisation Studio - unofficial git repo
C++
6
star
18

systrace

Unofficial mirror of systrace project
C
5
star
19

openssl

openssl repo clone
C
5
star
20

smalltable

Historical copy of http://code.google.com/p/smalltable
C
4
star
21

tornadopuka

Python
4
star
22

ydb

YDB, why not?
C
3
star
23

uclibc-vx32

C
3
star
24

libmsock

C
3
star
25

rons

RonS - simple pub/sub Redis client for Tornado
Python
3
star
26

rabbitmq-x-presence

RabbitMQ x-presence exchange (outdated)
Erlang
3
star
27

flying-squirrel-node

Flying-Squirrel server implementation using Node.js
JavaScript
2
star
28

ydb-old

Historical copy of http://code.google.com/p/ydb
C
2
star
29

sicp

Python
2
star
30

pats

Python
1
star
31

luasocket-vx32

C
1
star
32

sockjs-protocol

Repo migrated - https://github.com/sockjs/sockjs-protocol
1
star
33

wdl

http://cockos.com/wdl/ - unofficial git clone
C
1
star
34

p0f.popcount.org

Python
1
star
35

derponk5000

CoffeeScript
1
star
36

mdx

Simple markdown extensions
Ruby
1
star
37

popcount.org

1
star
38

codejam-practice

practice for codejam
Python
1
star
39

puka_pool

Python
1
star
40

rabbitmq-heroku-example

Ruby
1
star
41

rfc6455-client-erlang

WebSocket client for Erlang
Erlang
1
star
42

sockjs-node

Repo migrated: https://github.com/sockjs/sockjs-node
1
star
43

idea

Blog source: Marek's idea of the day
Python
1
star
44

ziutek

A historical clone of http://code.google.com/p/ziutek
Python
1
star
45

rmqstress

CoffeeScript
1
star