Streamlining systemd's code and safety
2017-10-21, 15:00–15:25 (UTC), Event Loft

Today, the systemd project uses a non-standard superset of C to get destructor-like functionality. But, we pay a heavy price for doing it this way: we lose compiler portability, use hundreds of boilerplate macros, and confuse static analysis tools (which don't always realize why we're not leaking memory). At compilation, the cleanup functionality gets mapped to the same facilities that handle C++ destructors. So, essentially, we're already using a non-standard version of C++ as well as a non-standard version of C. We can end this charade by following in GCC's footsteps and explicitly using a subset of C++. By doing so, we can shed thousands of lines of C-trying-to-be-C++. We can also improve memory safety and code readability -- all while keeping the feel of C.


Today, the systemd project uses a non-standard superset of C to get destructor-like functionality. But, we pay a heavy price for doing it this way: we lose compiler portability, use hundreds of boilerplate macros, and confuse static analysis tools (which don't always realize why we're not leaking memory). At compilation, the cleanup functionality gets mapped to the same facilities that handle C++ destructors. So, essentially, we're already using a non-standard version of C++ as well as a non-standard version of C. We can end this charade by following in GCC's footsteps and explicitly using a subset of C++. By doing so, we can shed thousands of lines of C-trying-to-be-C++. We can also improve memory safety and code readability -- all while keeping the feel of C.

In this presentation, we'll consider options for systems'd codebase:

  • Converting instances of "cleanup" to destructors. This should allow us to discard a couple thousand lines of boilerplate and many "goto cleanup" situations.
  • Converting raw pointers to equivalents with enforced semantics. For internal APIs, this should clarify handoff of memory ownership. For event loops, this should allow typed user data.
  • While I'm no advocate of object-orientation, our concept of a "unit" cleanly maps to an abstract superclass. IDEs and code analysis tools will benefit from moving away from homegrown inheritance.
  • We often return error codes as ints, and it would be good to explicitly use a real type instead. This will make refactoring easier if we change a function between returning an int vs. error vs. boolean.
  • The journal would benefit from a higher-level storage library like RocksDB (which offers a slim version for resource-constrained environments). Libraries like RocksDB are possible to use from C but have a richer (and easier-to-use) C++ API.