blob: ed653b9c2e2f58bad7acd9f9b5073c7c2263bd64 [file] [log] [blame]
Craig Tillerc21a8092015-05-15 10:03:40 -07001/*
2 *
Craig Tiller6169d5f2016-03-31 07:46:18 -07003 * Copyright 2015, Google Inc.
Craig Tillerc21a8092015-05-15 10:03:40 -07004 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following disclaimer
14 * in the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Google Inc. nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
33
34#include <grpc/support/port_platform.h>
35
36#ifdef GPR_POSIX_SUBPROCESS
37
38#include <grpc/support/subprocess.h>
39
Craig Tillerc21a8092015-05-15 10:03:40 -070040#include <assert.h>
41#include <errno.h>
Craig Tillerc21a8092015-05-15 10:03:40 -070042#include <signal.h>
Mark D. Roth491d9752016-11-28 10:39:00 -080043#include <stdbool.h>
Craig Tillerf40df232016-03-25 13:38:14 -070044#include <stdio.h>
Craig Tillerc21a8092015-05-15 10:03:40 -070045#include <stdlib.h>
Craig Tillerf40df232016-03-25 13:38:14 -070046#include <string.h>
Craig Tillerc21a8092015-05-15 10:03:40 -070047#include <sys/types.h>
48#include <sys/wait.h>
Craig Tillerf40df232016-03-25 13:38:14 -070049#include <unistd.h>
Craig Tillerc21a8092015-05-15 10:03:40 -070050
51#include <grpc/support/alloc.h>
52#include <grpc/support/log.h>
53
54struct gpr_subprocess {
55 int pid;
Mark D. Roth491d9752016-11-28 10:39:00 -080056 bool joined;
Craig Tillerc21a8092015-05-15 10:03:40 -070057};
58
Julien Boeufc1f3f2d2015-05-18 21:09:23 -070059const char *gpr_subprocess_binary_extension() { return ""; }
Craig Tillerc21a8092015-05-15 10:03:40 -070060
Craig Tillerfbac5f12015-05-15 14:20:44 -070061gpr_subprocess *gpr_subprocess_create(int argc, const char **argv) {
Craig Tillerc21a8092015-05-15 10:03:40 -070062 gpr_subprocess *r;
63 int pid;
64 char **exec_args;
65
66 pid = fork();
67 if (pid == -1) {
68 return NULL;
69 } else if (pid == 0) {
murgatroid995e71d7a2015-06-19 12:24:44 -070070 exec_args = gpr_malloc(((size_t)argc + 1) * sizeof(char *));
71 memcpy(exec_args, argv, (size_t)argc * sizeof(char *));
Craig Tillerc21a8092015-05-15 10:03:40 -070072 exec_args[argc] = NULL;
73 execv(exec_args[0], exec_args);
74 /* if we reach here, an error has occurred */
75 gpr_log(GPR_ERROR, "execv '%s' failed: %s", exec_args[0], strerror(errno));
76 _exit(1);
77 return NULL;
78 } else {
Craig Tiller6f417882017-02-16 14:09:39 -080079 r = gpr_zalloc(sizeof(gpr_subprocess));
Craig Tillerc21a8092015-05-15 10:03:40 -070080 r->pid = pid;
81 return r;
82 }
83}
84
85void gpr_subprocess_destroy(gpr_subprocess *p) {
86 if (!p->joined) {
87 kill(p->pid, SIGKILL);
88 gpr_subprocess_join(p);
89 }
90 gpr_free(p);
91}
92
93int gpr_subprocess_join(gpr_subprocess *p) {
94 int status;
Craig Tillerfbac5f12015-05-15 14:20:44 -070095retry:
Craig Tillerc21a8092015-05-15 10:03:40 -070096 if (waitpid(p->pid, &status, 0) == -1) {
Craig Tillerfbac5f12015-05-15 14:20:44 -070097 if (errno == EINTR) {
98 goto retry;
99 }
David Garcia Quintasa05909f2016-11-28 18:02:52 -0800100 gpr_log(GPR_ERROR, "waitpid failed for pid %d: %s", p->pid,
101 strerror(errno));
Craig Tillerc21a8092015-05-15 10:03:40 -0700102 return -1;
103 }
Mark D. Roth491d9752016-11-28 10:39:00 -0800104 p->joined = true;
Craig Tillerc21a8092015-05-15 10:03:40 -0700105 return status;
106}
107
108void gpr_subprocess_interrupt(gpr_subprocess *p) {
109 if (!p->joined) {
110 kill(p->pid, SIGINT);
111 }
112}
113
114#endif /* GPR_POSIX_SUBPROCESS */