4 ms·
C/POSIX permits a simple (albeit wildly inefficient) implementation that handles crashing: #include <stdlib.h> #include <unistd.h> #include <sys/types.h>
by colanderman 7y ago
C/POSIX permits a simple (albeit wildly inefficient) implementation that handles crashing:
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
// Return an integer in the range [0, n) which
// causes execution to succeed.
unsigned amb(const unsigned n)
{
if (n == 0) _exit(42);
for (unsigned i = 0; i < n - 1; ++i)
{
const pid_t child = fork();
if (child < 0) abort();
if (child == 0) return i;
int wstatus;
if (waitpid(child, &wstatus, 0) < 0) abort();
if (WIFEXITED(wstatus) && WEXITSTATUS(wstatus) == 0) _exit(0);
}
return n - 1;
}
You could of course parallelize this to handle nontermination, at the expensive of potentially many concurrent processes for a high n.
You can make other fun time-traveling functions following the above pattern. My favorite I call the "Groundhog Day" function, or "Cause and Effect" for Star Trek fans: when first called, it returns zero; if the program later fails, it is restarted from that function call, which returns the exit code. (I'm not really sure how useful this is.)