|
8 | 8 | #include "util.h" |
9 | 9 |
|
10 | 10 | #include <algorithm> |
| 11 | +#include <cerrno> |
11 | 12 | #include <csignal> |
12 | 13 | #include <cstring> |
13 | 14 | #include <fstream> |
@@ -2336,15 +2337,52 @@ int Util::System(const std::string& p_Cmd) |
2336 | 2337 | static const std::string shPath = "/bin/sh"; |
2337 | 2338 | #endif |
2338 | 2339 |
|
| 2340 | + // Block SIGCHLD and ignore SIGINT/SIGQUIT in parent per POSIX system() spec |
| 2341 | + struct sigaction saIgnore; |
| 2342 | + struct sigaction saOrigInt; |
| 2343 | + struct sigaction saOrigQuit; |
| 2344 | + saIgnore.sa_handler = SIG_IGN; |
| 2345 | + sigemptyset(&saIgnore.sa_mask); |
| 2346 | + saIgnore.sa_flags = 0; |
| 2347 | + sigaction(SIGINT, &saIgnore, &saOrigInt); |
| 2348 | + sigaction(SIGQUIT, &saIgnore, &saOrigQuit); |
| 2349 | + |
| 2350 | + sigset_t blockChld; |
| 2351 | + sigset_t origMask; |
| 2352 | + sigemptyset(&blockChld); |
| 2353 | + sigaddset(&blockChld, SIGCHLD); |
| 2354 | + sigprocmask(SIG_BLOCK, &blockChld, &origMask); |
| 2355 | + |
2339 | 2356 | pid_t pid = fork(); |
2340 | 2357 | if (pid == 0) |
2341 | 2358 | { |
| 2359 | + // Child: restore original signal dispositions and mask |
| 2360 | + sigaction(SIGINT, &saOrigInt, nullptr); |
| 2361 | + sigaction(SIGQUIT, &saOrigQuit, nullptr); |
| 2362 | + sigprocmask(SIG_SETMASK, &origMask, nullptr); |
| 2363 | + |
2342 | 2364 | execl(shPath.c_str(), "sh", "-c", p_Cmd.c_str(), (char*)nullptr); |
2343 | 2365 | _exit(127); |
2344 | 2366 | } |
2345 | 2367 |
|
2346 | | - if (pid < 0) return -1; |
| 2368 | + int status = -1; |
| 2369 | + if (pid > 0) |
| 2370 | + { |
| 2371 | + // Retry waitpid on EINTR (e.g. from SIGWINCH during terminal resize) |
| 2372 | + while (waitpid(pid, &status, 0) < 0) |
| 2373 | + { |
| 2374 | + if (errno != EINTR) |
| 2375 | + { |
| 2376 | + status = -1; |
| 2377 | + break; |
| 2378 | + } |
| 2379 | + } |
| 2380 | + } |
| 2381 | + |
| 2382 | + // Restore original signal dispositions and mask |
| 2383 | + sigaction(SIGINT, &saOrigInt, nullptr); |
| 2384 | + sigaction(SIGQUIT, &saOrigQuit, nullptr); |
| 2385 | + sigprocmask(SIG_SETMASK, &origMask, nullptr); |
2347 | 2386 |
|
2348 | | - int status = 0; |
2349 | | - return (waitpid(pid, &status, 0) < 0) ? -1 : status; |
| 2387 | + return status; |
2350 | 2388 | } |
0 commit comments