I recently learned how to make the whole fork/exec/wait
tag, and ended up writing code that looked like this:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> int main() { pid_t x = fork(); if (x == 0) { execlp("sqlite3", "sqlite3"); printf("exec failed\n"); } else { wait(NULL); printf("Hi\n"); } }
This works pretty well, and the sqlite3
shell sqlite3
, but there is one problem. If you sqlite3
Ctrl + C
from the sqlite3
shell, then it will also terminate the parent process, and the printf("Hi\n")
will never start.
I assumed that this was due to the fact that SIGINT extended to the parent process, and, having studied it further, I read that SIGINT will terminate all processes in the same group, that is, since the parent and child have the same same group, they are both completed.
I tried to fix this by trying to call setpgid
as follows:
int main() { pid_t x = fork(); if (x == 0) { setpgid(getpid(), getpid()); // <-- Added in this line execlp("sqlite3", "sqlite3"); printf("exec failed\n"); } else { wait(NULL); printf("Hi\n"); } }
which works fine, but that broke the sqlite3
. Moreover, Ctrl + C
still killed the parent in this case. I decided to try to narrow it down even more, and then I found something strange and stalled. Simply placing the getpid()
call in the fork will cause execlp()
to crash.
#include <stdio.h> #include <stdlib.h> #include <unistd.h> int main() { pid_t x = fork(); if (x == 0) { getpid(); // <--- just adding this in makes it fail execlp("sqlite3", "sqlite3"); printf("exec failed\n"); } else { wait(NULL); printf("Hi\n"); } }
and not even for sqlite3
, but for simple things like execlp("ls", "ls")
(this may not be related to the original question).
I'm a little over my head and I was wondering if anyone could point me in the right direction. I'm not quite sure what to do next.
- I'm on OSX 10.11 and compiling with clang.
clang --version
: Apple LLVM version 8.0.0 (clang-800.0.42.1)