Skip to content

Commit c56bd3b

Browse files
committed
feat: use thread
1 parent 84d139b commit c56bd3b

1 file changed

Lines changed: 37 additions & 25 deletions

File tree

unix/watcher_unix.cpp

Lines changed: 37 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@
66
*
77
*/
88

9+
#include <atomic>
910
#include <cassert>
1011
#include <cerrno>
12+
#include <chrono>
1113
#include <csignal>
1214
#include <cstdio>
1315
#include <cstdlib>
@@ -20,19 +22,20 @@
2022
#include <sys/time.h>
2123
#include <sys/types.h>
2224
#include <sys/wait.h>
25+
#ifdef __linux__
26+
#include <sys/syscall.h>
27+
#endif
28+
#include <thread>
2329
#include <unistd.h>
2430
#include <vector>
2531

2632
static int pid;
27-
static volatile sig_atomic_t timedOut;
2833

2934
static void cleanUp(int /*dummy*/) {
3035
kill(pid, SIGKILL);
3136
exit(0);
3237
}
3338

34-
static void alarmHandler(int /*dummy*/) { timedOut = 1; }
35-
3639
extern void initWatcher();
3740
extern ssize_t calculateStaticMemoryUsage(const std::string &);
3841
extern ssize_t getMemoryRLimit(ssize_t memoryLimitInMB);
@@ -155,41 +158,50 @@ auto main(int argc, char *argv[]) -> int {
155158
pid = fork();
156159

157160
if (pid > 0) {
158-
// Parent process
159161
signal(SIGINT, cleanUp);
160162
signal(SIGABRT, cleanUp);
161163
signal(SIGTERM, cleanUp);
162164

163-
struct sigaction sa;
164-
sa.sa_handler = alarmHandler;
165-
sigemptyset(&sa.sa_mask);
166-
sa.sa_flags = 0;
167-
sigaction(SIGALRM, &sa, nullptr);
168-
169165
long long wallClockMs = timeLimitMs + extraTimeMs;
170-
struct itimerval timer;
171-
timer.it_value.tv_sec = wallClockMs / 1000;
172-
timer.it_value.tv_usec = (wallClockMs % 1000) * 1000;
173-
timer.it_interval = {0, 0};
174-
setitimer(ITIMER_REAL, &timer, nullptr);
175166

176-
struct rusage usage{};
177-
int status = 0;
167+
int childPfd = -1;
168+
#ifdef __linux__
169+
childPfd = syscall(SYS_pidfd_open, pid, 0);
170+
#endif
178171

179-
if (wait4(pid, &status, 0, &usage) == -1) {
180-
if (errno == EINTR && timedOut) {
181-
kill(pid, SIGKILL);
182-
wait4(pid, nullptr, 0, nullptr);
183-
printf("-1\n-1\n");
184-
return RS_TLE;
172+
auto timedOut = std::make_shared<std::atomic<bool>>(false);
173+
auto done = std::make_shared<std::atomic<bool>>(false);
174+
175+
std::thread([=]() {
176+
std::this_thread::sleep_for(std::chrono::milliseconds(wallClockMs));
177+
if (!*done) {
178+
*timedOut = true;
179+
#ifdef __linux__
180+
if (childPfd >= 0)
181+
syscall(SYS_pidfd_send_signal, childPfd, SIGKILL, NULL, 0);
182+
else
183+
#endif
184+
kill(pid, SIGKILL);
185185
}
186+
}).detach();
187+
188+
struct rusage usage{};
189+
int status;
190+
191+
while (wait4(pid, &status, 0, &usage) == -1) {
192+
if (errno == EINTR)
193+
continue;
186194
printf("-1\n-1\n");
187195
perror("wait4");
188196
return RS_FAIL;
189197
}
190198

191-
struct itimerval disable = {{0, 0}, {0, 0}};
192-
setitimer(ITIMER_REAL, &disable, nullptr);
199+
*done = true;
200+
201+
if (*timedOut) {
202+
printf("-1\n-1\n");
203+
return RS_TLE;
204+
}
193205

194206
if (WIFEXITED(status)) {
195207
long long timeUsedMs =

0 commit comments

Comments
 (0)