/* * * Copyright 2015 gRPC authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include #ifdef GPR_POSIX_SUBPROCESS #include #include #include #include #include #include #include #include #include #include #include #include #include struct gpr_subprocess { int pid; bool joined; }; const char *gpr_subprocess_binary_extension() { return ""; } gpr_subprocess *gpr_subprocess_create(int argc, const char **argv) { gpr_subprocess *r; int pid; char **exec_args; pid = fork(); if (pid == -1) { return NULL; } else if (pid == 0) { exec_args = (char **)gpr_malloc(((size_t)argc + 1) * sizeof(char *)); memcpy(exec_args, argv, (size_t)argc * sizeof(char *)); exec_args[argc] = NULL; execv(exec_args[0], exec_args); /* if we reach here, an error has occurred */ gpr_log(GPR_ERROR, "execv '%s' failed: %s", exec_args[0], strerror(errno)); _exit(1); return NULL; } else { r = (gpr_subprocess *)gpr_zalloc(sizeof(gpr_subprocess)); r->pid = pid; return r; } } void gpr_subprocess_destroy(gpr_subprocess *p) { if (!p->joined) { kill(p->pid, SIGKILL); gpr_subprocess_join(p); } gpr_free(p); } int gpr_subprocess_join(gpr_subprocess *p) { int status; retry: if (waitpid(p->pid, &status, 0) == -1) { if (errno == EINTR) { goto retry; } gpr_log(GPR_ERROR, "waitpid failed for pid %d: %s", p->pid, strerror(errno)); return -1; } p->joined = true; return status; } void gpr_subprocess_interrupt(gpr_subprocess *p) { if (!p->joined) { kill(p->pid, SIGINT); } } #endif /* GPR_POSIX_SUBPROCESS */