Skip to content

Repository files navigation

Build

rtcheck

Dynamic library to catch run-time safety violations heavily inspired by RADSan

Contents

Adding rtcheck to a project

CMake option 1: Git Submodule

git submodule add -b main https://github.com/Tracktion/rtcheck rtcheck

To update down the road:

git submodule update --remote --merge rtcheck

Build rtcheck as part of your CMakeLists.txt

add_subdirectory(rtcheck)

CMake option 2: FetchContent

Include(FetchContent)
FetchContent_Declare(rtcheck
GIT_REPOSITORY https://github.com/Tracktion/rtcheck.git
GIT_TAG origin/main
SOURCE_DIR${CMAKE_CURRENT_BINARY_DIR}/rtcheck)
FetchContent_MakeAvailable(rtcheck)

Link rtcheck to your CMake project

target_link_libraries("YourProject"PRIVATErtcheck)

Then include rtcheck in your source files:

#include<rtcheck.h>

Using rtcheck

Simply add an instance of rtc::realtime_context at the start of the scope you want to check for real-time safety violations like this:

intmain()
{
std::thread t ([]
{
rtc::realtime_context rc;
malloc (1024); // Allocating memory is a real-time safety violation!
});
t.join();
return0;
}

The call to malloc in the above code will then be caught and logged as so:

Real-time violation: intercepted call to real-time unsafe function malloc in real-time context! Stack trace:
0 librt_check.dylib 0x000000010543f7d4 _ZN3rtc14get_stacktraceEv + 84
1 librt_check.dylib 0x000000010543f450 _ZN3rtc32log_function_if_realtime_contextEPKc + 300
2 librt_check.dylib 0x000000010543fe00 _Z44log_function_if_realtime_context_and_enabledN3rtc11check_flagsEPKc + 64
3 librt_check.dylib 0x000000010543fe30 wrap_malloc + 32
4 fail_malloc 0x0000000104fcff14 main + 32
5 dyld 0x00000001901760e0 start + 2360

Disabling checks

There are two ways to disable checks. You can either disable all checks, which can be useful if you know you'll be calling a potentially unsafe function but in a safe way (e.g. an un-contented lock), or you want to log something:

{
rtc::non_realtime_context nrc;
std::cout << "need to get this message on the screen!";
}

Or you can selectively disable checks:

{
rtc::disable_checks_for_thread (check_flags::threads);
mutex.lock(); // I know this is uncontended, don't for get to unlock!
}

Catching your own violations

If you have some code which you know is non-real-time safe e.g. an unbounded distribution function or some other async call, you can opt-in to let rtcheck catch it by calling the following function:

voidmy_unsafe_function()
{
log_function_if_realtime_context (__func__);
}

This will then get logged if called whilst a rtc::realtime_context is alive.

Error Modes

There are two currently supported error modes

  • Exit with error code 1 (default)
  • Log and continue

Exiting it useful for CI runs where you want the program to terminate in an obvious way (non-zero exit code) to fail the run. In normal use though, you may just want to log the violation and continue.

You can change between these globally using the following function:

/** Sets the global error more to determine the behaviour when a real-time violation is detected.*/voidset_error_mode (error_mode);

Notes:

Features

  • Enable in scope
  • Disable in scope
  • Symbolicated stack-trace
  • Run-time options for checks
  • Opt-in for own code
  • linux
  • macOS (malloc unsupported)
  • Add option to realtime_context constructor to disable checks for that scope
  • Delay time

Functions (test = ✔)

  • Time
    • sleep ✔
    • nanosleep ✔
    • usleep ✔
  • Memory
    • malloc ✔
    • calloc ✔
    • realloc ✔
    • free ✔
    • reallocf (macOS) ✔
    • valloc ✔
    • posix_memalign ✔
    • mmap ✔
    • munmap ✔
  • Threads
    • pthread_create ✔
    • pthread_mutex_lock ✔
    • pthread_mutex_unlock ✔
    • pthread_join ✔
    • pthread_cond_signal
    • pthread_cond_broadcast
    • pthread_cond_wait
    • pthread_cond_timedwait
    • pthread_rwlock_rdlock ✔
    • pthread_rwlock_unlock ✔
    • pthread_rwlock_wrlock ✔
    • pthread_spin_lock (linux)
  • Files
    • open ✔
    • openat
    • close
    • fopen
    • fread
    • fwrite
    • fclose
    • fcntl ✔
    • creat
    • puts
    • fputs
    • stat ✔
    • stat64
    • fstat
    • fstat64
  • IO
    • socket
    • send
    • sendmsg
    • sendto
    • recv
    • recvmsg
    • recvfrom
    • shutdown
  • System calls
    • syscall ✔
    • schedule
    • context_switch

CI/Tests

  • Failures
    • Throwing exceptions
    • Large std::function
    • Atomic 4*ptr size
    • Dynamic loading of a library
  • Passes
    • Atomic double
    • Small std::function
    • thread_local? (pass on linux, fail on macOS)
  • Running on CI Linux
  • Running on CI macOS
  • Tests via CTest (can catch failues)

Packages

  • cpack
  • conan
  • vcpkg

About

Dynamic library to catch run-time safety violations

Resources

Stars

23 stars

Watchers

4 watching

Forks

Releases

Packages

Used by

Contributors

Languages