The Problem: Why is std::abort() So Slow?

When writing crash-recovery unit tests (such as GoogleTest Death Tests), simulating a sudden crash is a common requirement. However, calling std::abort() can introduce a massive delay—often taking anywhere from 5 to 12 seconds to actually terminate the process.

This delay is almost never caused by C++ cleanup. Instead, it is caused by the Operating System generating a core dump. When std::abort() is called, it raises the SIGABRT signal. By default, Linux attempts to write the entire memory footprint of your process to a core dump file. If your system has services like systemd-coredump or apport enabled, they will intercept, process, and often compress this dump, resulting in the multi-second lag you are experiencing.

Fortunately, there are several ways to programmatically terminate a process instantly, depending on whether you need to simulate a signal-based crash or just want an immediate exit.

Solution 1: Terminate Instantly with _exit() or _Exit()

If you do not strictly need a crash signal (like SIGABRT or SIGSEGV) and just want the process to stop immediately without any cleanup, use _exit() (POSIX) or _Exit() (C++11).

Unlike std::exit(), these functions do not call destructors, do not flush stdio buffers, do not run std::atexit handlers, and do not trigger a core dump. They make a direct system call to terminate the process instantly.

#include <unistd.h> // For POSIX _exit
#include <cstdlib>  // For C++11 _Exit

void crash_instantly() {
    // Exit immediately with a non-zero status code
    _exit(EXIT_FAILURE); 
}

Solution 2: Send SIGKILL to Yourself

If your test framework or environment expects the process to terminate via a signal rather than a normal exit code, you can send a SIGKILL signal to your own process. Unlike SIGABRT or SIGSEGV, SIGKILL (Signal 9) cannot be caught, blocked, or ignored, and by default, it does not generate a core dump.

#include <sys/types.h>
#include <signal.h>
#include <unistd.h>

void crash_via_sigkill() {
    // Send SIGKILL to the current process
    kill(getpid(), SIGKILL);
}

Alternatively, you can use the standard library's raise function:

#include <csignal>

void crash_via_raise() {
    std::raise(SIGKILL);
}

Solution 3: Disable Core Dumps and Keep std::abort()

If you are using GoogleTest's ASSERT_DEATH or EXPECT_DEATH and your test suite specifically asserts that the process died due to SIGABRT (which is what std::abort() sends), you cannot switch to _exit() or SIGKILL.

In this scenario, the best solution is to programmatically disable core dumps for your process using setrlimit before triggering the abort. This keeps the SIGABRT behavior but eliminates the OS-level disk writing overhead.

#include <sys/resource.h>
#include <cstdlib>

void abort_without_coredump() {
    struct rlimit limit;
    limit.rlim_cur = 0; // Set resource limit to 0
    limit.rlim_max = 0;
    
    // Disable core dumps for this process
    setrlimit(RLIMIT_CORE, &limit);
    
    // Now abort instantly
    std::abort();
}

Summary: Which Approach Should You Use?

  • Use _exit(code): If you just need the process to stop immediately and don't care about simulating a signal-based crash.
  • Use raise(SIGKILL): If you want to simulate a sudden, uncatchable OS-level termination without any core dump delay.
  • Use setrlimit + std::abort(): If your testing framework (like GTest) specifically validates that the process terminated via SIGABRT.