Skip to content

Commit

Permalink
Safer checks for pipe and dummy_pipe
Browse files Browse the repository at this point in the history
  • Loading branch information
wch committed Dec 1, 2020
1 parent 44d115d commit b7ec34c
Showing 1 changed file with 53 additions and 12 deletions.
65 changes: 53 additions & 12 deletions src/later_posix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,11 @@ int initialized = 0;
// The handles to the read and write ends of a pipe. We use this pipe
// to signal R's input handler callback mechanism that we want to be
// called back.
int pipe_in, pipe_out;
int pipe_in = -1;
int pipe_out = -1;

int dummy_pipe_in, dummy_pipe_out;
int dummy_pipe_in = -1;
int dummy_pipe_out = -1;

// Whether the file descriptor is ready for reading, i.e., whether
// the input handler callback is scheduled to be called. We use this
Expand Down Expand Up @@ -147,21 +149,40 @@ InputHandler* dummyInputHandlerHandle;
static void remove_dummy_handler(void *data) {
ASSERT_MAIN_THREAD()
removeInputHandler(&R_InputHandlers, dummyInputHandlerHandle);
close(dummy_pipe_in);
close(dummy_pipe_out);
if (dummy_pipe_in > 0) {
close(dummy_pipe_in);
dummy_pipe_in = -1;
}
if (dummy_pipe_out > 0) {
close(dummy_pipe_out);
dummy_pipe_out = -1;
}
}

void deInitialize() {
// Callback to run in child process after forking.
void child_proc_after_fork() {
ASSERT_MAIN_THREAD()
if (initialized) {
removeInputHandler(&R_InputHandlers, inputHandlerHandle);
close(pipe_in);
close(pipe_out);
initialized = 0;

// Trigger remove_dummy_handler()
// Store `ret` because otherwise it raises a significant warning.
ssize_t ret = write(dummy_pipe_in, "a", 1);
if (pipe_in > 0) {
close(pipe_in);
pipe_in = -1;
}
if (pipe_out > 0) {
close(pipe_out);
pipe_out = -1;
}
if (dummy_pipe_in > 0) {
close(dummy_pipe_in);
dummy_pipe_in = -1;
}
if (dummy_pipe_out > 0) {
close(dummy_pipe_out);
dummy_pipe_out = -1;
}

initialized = 0;
}
}

Expand All @@ -187,7 +208,7 @@ void ensureAutorunnerInitialized() {
// the parent process and then will be executed in the child process (in
// addition to in the parent process).
// https://github.com/r-lib/later/issues/140
pthread_atfork(NULL, NULL, deInitialize);
pthread_atfork(NULL, NULL, child_proc_after_fork);

// Need to add a dummy input handler to avoid segfault when the "real"
// input handler removes the subsequent input handler in the linked list.
Expand All @@ -205,6 +226,26 @@ void ensureAutorunnerInitialized() {
}
}

void deInitialize() {
ASSERT_MAIN_THREAD()
if (initialized) {
removeInputHandler(&R_InputHandlers, inputHandlerHandle);
if (pipe_in > 0) {
close(pipe_in);
pipe_in = -1;
}
if (pipe_out > 0) {
close(pipe_out);
pipe_out = -1;
}
initialized = 0;

// Trigger remove_dummy_handler()
// Store `ret` because otherwise it raises a significant warning.
ssize_t ret = write(dummy_pipe_in, "a", 1);
}
}

uint64_t doExecLater(boost::shared_ptr<CallbackRegistry> callbackRegistry, Rcpp::Function callback, double delaySecs, bool resetTimer) {
ASSERT_MAIN_THREAD()
uint64_t callback_id = callbackRegistry->add(callback, delaySecs);
Expand Down

0 comments on commit b7ec34c

Please sign in to comment.