• Stars
    star
    1,189
  • Rank 39,340 (Top 0.8 %)
  • Language
    Rust
  • License
    Other
  • Created about 2 years ago
  • Updated about 1 month ago

Reviews

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

Repository Details

Hermit launches linux x86_64 programs in a special, hermetically isolated sandbox to control their execution. Hermit translates normal, nondeterministic behavior, into deterministic, repeatable behavior. This can be used for various applications, including replay-debugging, reproducible artifacts, chaos mode concurrency testing and bug analysis.

Hermit: A reproducible container

Hermit forces deterministic execution of arbitrary programs and acts like a reproducible container. That is, it hermetically isolates the program from sources of non-determinism such as time, thread interleavings, random number generation, etc. Guaranteed determinism is a powerful tool and it serves as a basis for a number of applications, including concurrency stress testing, record/replay, reproducible builds, and automatic diagnosis of concurrency bugs, and more.

Hermit cannot isolate the guest program from sources of non-determinism such as file system changes or external network responses. Instead, in order to provide complete determinism, the user should provide a fixed file system base image (e.g., with Docker) and disable external networking.

How it works

Hermit sits between the guest process and the OS intercepting system calls made by the guest (using Reverie). In some cases, it can completely replace the functionality of the kernel and suppress the original system call. In other cases, it forwards the system call to the kernel and sanitizes the response such that it is made deterministic.

As a concrete example, lets say we have a program that reads random bytes from /dev/urandom. Hermit will see that the guest opened this file (a known source of non-determinism) and intercept subsequent reads to this file. Instead of letting the OS fill a buffer with random bytes, Hermit uses a deterministic pseudorandom number generator with a fixed seed to fill in the buffer. The contents of the buffer are then guaranteed to be the same upon every execution of the program.

The most complex source of non-determinism is in the thread scheduler. The way threads are scheduled by the kernel depends on many external factors, including the number of physical CPUs or other threads running on the system that require CPU time. To ensure that the threads of the guest process (and all of its child processes) are scheduled in a repeatable way, we first make sure that all thread executions are serialized so that there is effectively only one CPU. Then, we deterministically pick which thread is allowed to run next. In order to only allow a thread to run for a fixed number of instructions, we use the CPU's Performance Monitoring Unit (PMU) to stop execution after a fixed number of retired conditional branches (RCBs).

Read below about how to build Hermit, and you can get an idea of what it does from running examples in the ./examples folder.

Building and running Hermit

Hermit is built with the standard Rust cargo tool.

cargo build

This builds the whole cargo workspace. The actual binary is located in target directory (target/debug/hermit).

Then, once you've built Hermit, all you need to run your program deterministically is:

hermit run <prog>

After that you can try running it in a concurrency stress testing (chaos) mode, or varying other parameters of the configuration such as the speed at which virtual time passes inside the container, or the random number generation seed:

hermit run --chaos --sched-seed=3 <prog>

You can use hermit as a replay-debugger as well, either recording a non-deterministic execution (real time, real randomness, etc), or repeatedly running a controlled, deterministic one (virtual time, pseudo-randomness, etc).

hermit record start <prog>
hermit replay

Example programs

See the the examples folder for example programs and instructions on how to run them. These showcase different sources of nondeterminism, and how hermit eliminates or controls them.

In order to explore more advanced examples, you can look at some of the integration tests built from ./tests/ or ./flaky-tests/. For example, using the commands below you can run a racy example multiple times to see its nondeterminism. Then run it under hermit to watch that determinism disappear. Then run it under hermit --chaos to bring that nondeterminism back, but in a controlled way that can be reproduced based on the input seed.

cargo build
for ((i=0; i<20; i++)); do ./target/debug/hello_race; done

for ((i=0; i<20; i++)); do hermit run ./target/debug/hello_race; done

for ((i=0; i<20; i++)); do
  hermit run --chaos --seed-from=SystemRandom ./target/debug/hello_race;
done

The state of CI and testing

At Meta, this repository is built using buck. We have over 700 integration tests that run under this setup. But as of this initial release (2022-11-21), we have not ported these tests to an external build system yet.

A few unit tests run under cargo test, but the integration tests are more complicated because they combine various run modes with each of the test binaries (which are built from tests/, flaky-tests/, and the rr test suite too).

We plan to get the internal Buck configuration files building externally with buck or bazel.

Applications

Hermit translates normal, non-deterministic Linux behavior, into deterministic, repeatable behavior. This can be used for various applications, including: record/replay debugging, simple reproducibility, "chaos mode" to expose concurrency bugs in a controlled and repeatable way. Generally, Hermit makes implicit inputs into explicit ones, and so enables searching over possible executions by explicitly varying these inputs and study the changes in outcomes. This can be used for either searching for bugs or trying to narrow down their causes.

Diagnosing concurrency bugs

One experimental application that Hermit has built-in support for is diagnosing concurrency bugs, in terms of identifying the stack traces of racing critical operations which, if their order is flipped in the schedule, cause the program to crash (also called an "order violation" bug). Hermit can detect these even if the racing instructions are in different processes and written in different programming languages.

You can kick off analyze with any program invocation, and tell it to search for failing (and passing) executions, and then diagnose the difference between them.

hermit analyze --search -- <run_args> <prog>

License

Hermit is licensed under a BSD-3 clause license, included in the LICENSE file in this directory.

Support

Hermit currently supports x86_64 Linux. Aarch64 support is a work in progress.

More Repositories

1

Recoil

Recoil is an experimental state management library for React apps. It provides several capabilities that are difficult to achieve with React alone, while being compatible with the newest features of React.
JavaScript
19,610
star
2

libunifex

Unified Executors
C++
1,479
star
3

Robyn

Robyn is an experimental, AI/ML-powered and open sourced Marketing Mix Modeling (MMM) package from Meta Marketing Science. Our mission is to democratise modeling knowledge, inspire the industry through innovation, reduce human bias in the modeling process & build a strong open source marketing science community.
Jupyter Notebook
1,104
star
4

MIRAI

Rust mid-level IR Abstract Interpreter
Rust
1,004
star
5

reverie

An ergonomic and safe syscall interception framework for Linux.
Rust
544
star
6

ExtendedAndroidTools

Extended Android Tools is a place to host and maintain a build environment and makefiles cross compiling Linux tools we all love for Android.
Python
174
star
7

object-introspection

Object Introspection (OI) enables on-demand, hierarchical profiling of objects in arbitrary C/C++ programs with no recompilation.
C++
153
star
8

resctl-demo

Demonstrate and benchmark various features of Linux resource control in a self-contained package.
Rust
149
star
9

allocative

Library and proc macro to analyze memory usage of data structures in rust.
Rust
125
star
10

rust-shed

Repository containing Rust crates common between other Facebook open source projects (like Mononoke or Eden).
Rust
102
star
11

go-media-webtransport-server

WebTransport media server that enables ultra low latency live streaming over QUIC (also VOD and rewind)
Go
94
star
12

webcodecs-capture-play

Live streaming low latency experimentation platform in the browser (using WebCodecs)
JavaScript
88
star
13

moq-encoder-player

This project is provides a minimal implementation (inside the browser) of a live video and audio encoder and video / audio player creating and consuming IETF MOQ stream. The goal is to provide a minimal live platform components that helps testing IETF MOQ interop
HTML
50
star
14

siMMMulator

siMMMulator is an open source R-package that helps users to generate simulated data to plug into Marketing Mix Models (MMMs). The package features a variety of functions to help users build a data set from scratch.
R
45
star
15

moq-go-server

This is an experimental relay (optimized for low latency media transfers) that implements IETF MOQ protocol
Go
43
star
16

MemorySnapshotAnalyzer

Analysis tooling for memory snapshots of managed code runtimes, specifically, Unity Memory Snapshots.
C#
31
star
17

protoquant

Prototype routines for GPU quantization written using PyTorch.
Python
19
star
18

moxygen

Implementation of IETF MOQ protocol
Python
15
star
19

kperf

TCP and TLS performance testing tool.
C
11
star
20

edencommon

Shared library for Watchman and Eden projects.
C++
11
star
21

propellint

A tool joining profile information with static analysis.
C++
5
star
22

r8

Customized version of the D8 dexer and R8 shrinker
Java
5
star
23

usb-video

Android library and app for streaming content from USB Video Class (UVC) devices.
C++
4
star
24

CARL

Classical Action Recognition Library
C++
4
star
25

WMG

Serverless Application Model (SAM) project to deploy a Cloudformation insfrastructure capable of measuring signals in WhatsApp conversations.
JavaScript
3
star
26

iot-session-manager

The IoT Session Manager is an application that provides a reliable and scalable device to device messaging network with simple setup. The system is deployable locally on a machine or on a cloud server and provides extensible methods for device authentication and control automation.
Python
3
star
27

free-threading-benchmarking

Benchmark results for free-threaded builds of Python
3
star
28

xrpa

Xrpa (pronounced "zerpa") is a platform architecture framework for building experimental XR experiences.
C++
3
star
29

fnob

Open source Fnob (Command-line Dynamic Random Generator) package;
SystemVerilog
2
star
30

Rmdkernel

This is a very simple fork of https//github.com/IRkernel/IRkernel to provide an rmarkdown (rather than R) jupyter kernel.
Jupyter Notebook
2
star
31

ndctl

A "device memory" enabling project encompassing tools and libraries for CXL, NVDIMMs, DAX, memory tiering and other platform memory device topics. Forked from https://github.com/pmem/ndctl
C
2
star
32

csproj_benchmark

A tool that generates Visual Studio C# projects and measures IDE startup performance
C#
1
star