| #include <pthread.h> | |
| #include <signal.h> | |
| #include <sys/wait.h> | |
| #include <unistd.h> | |
| int fork_and_return(int value, bool use_vfork) { | |
| pid_t pid = use_vfork ? vfork() : fork(); | |
| if (pid == -1) | |
| return -1; | |
| if (pid == 0) { | |
| // child | |
| _exit(value); | |
| } | |
| // parent | |
| int status; | |
| waitpid(pid, &status, 0); | |
| return WEXITSTATUS(status); | |
| } | |
| int fork_and_return_trap(int value) { | |
| pid_t pid = fork(); | |
| if (pid == -1) | |
| return -1; | |
| if (pid == 0) { | |
| // child returning from the JITed function wrapper will hit a trap | |
| // instruction and terminate with SIGTRAP. | |
| return value; | |
| } | |
| // parent | |
| int status; | |
| waitpid(pid, &status, 0); | |
| if (WIFSIGNALED(status) && WTERMSIG(status) == SIGTRAP) { | |
| return 1; // Success: child terminated with SIGTRAP | |
| } | |
| return 0; // Failure | |
| } | |
| // Mutex-based synchronization for concurrent fork test. | |
| // The main thread holds the mutex, starts a helper thread that waits | |
| // on the mutex then forks, and the expression releases the mutex and | |
| // waits to reacquire it - forcing the fork to happen on a different | |
| // thread while the expression is running. | |
| static pthread_mutex_t g_fork_mutex = PTHREAD_MUTEX_INITIALIZER; | |
| static pid_t g_child_pid = -1; | |
| static void *concurrent_fork_thread(void *arg) { | |
| // Wait until the expression releases the mutex. | |
| pthread_mutex_lock(&g_fork_mutex); | |
| g_child_pid = fork(); | |
| if (g_child_pid == 0) { | |
| // child | |
| _exit(42); | |
| } | |
| // parent - release mutex so expression can reacquire. | |
| pthread_mutex_unlock(&g_fork_mutex); | |
| return nullptr; | |
| } | |
| // Called as an expression while another thread forks. | |
| // The caller must hold g_fork_mutex before evaluating this expression. | |
| int expr_with_concurrent_fork() { | |
| pthread_t t; | |
| pthread_create(&t, nullptr, concurrent_fork_thread, nullptr); | |
| // Release mutex - lets the helper thread proceed to fork. | |
| pthread_mutex_unlock(&g_fork_mutex); | |
| // Wait for the helper thread to finish (it forks and unlocks). | |
| pthread_join(t, nullptr); | |
| // Reacquire mutex to synchronize. | |
| pthread_mutex_lock(&g_fork_mutex); | |
| // Return the child PID so the test can verify fork happened. | |
| return (int)g_child_pid; | |
| } | |
| int main() { | |
| pthread_mutex_lock(&g_fork_mutex); | |
| int x = 42; | |
| return 0; // break here | |
| } |