aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Nicolas Noble <nicolasnoble@users.noreply.github.com>2015-05-15 14:13:52 -0700
committerGravatar Nicolas Noble <nicolasnoble@users.noreply.github.com>2015-05-15 14:13:52 -0700
commit9aaa1b61e7bd6a1173d6d7fb4b68ca8ae74bcabe (patch)
tree8cc2ead249be6288e1010aef9e799d9444724db0
parent26d916a9e6318ba35c94c51e0b9eac49816a308a (diff)
parent685f1e625553c5158280761d3b91c8875166f394 (diff)
Merge pull request #1617 from ctiller/force-a-crash-but-then-dont-crash
Add subprocess GPR API
-rw-r--r--BUILD2
-rw-r--r--Makefile2
-rw-r--r--build.json2
-rw-r--r--include/grpc/support/port_platform.h4
-rw-r--r--include/grpc/support/subprocess.h49
-rw-r--r--src/core/support/subprocess_posix.c108
-rw-r--r--test/core/fling/fling_test.c81
-rw-r--r--vsprojects/gpr/gpr.vcxproj3
-rw-r--r--vsprojects/gpr/gpr.vcxproj.filters6
9 files changed, 206 insertions, 51 deletions
diff --git a/BUILD b/BUILD
index 396e18d5a2..72da642bde 100644
--- a/BUILD
+++ b/BUILD
@@ -74,6 +74,7 @@ cc_library(
"src/core/support/string.c",
"src/core/support/string_posix.c",
"src/core/support/string_win32.c",
+ "src/core/support/subprocess_posix.c",
"src/core/support/sync.c",
"src/core/support/sync_posix.c",
"src/core/support/sync_win32.c",
@@ -101,6 +102,7 @@ cc_library(
"include/grpc/support/port_platform.h",
"include/grpc/support/slice.h",
"include/grpc/support/slice_buffer.h",
+ "include/grpc/support/subprocess.h",
"include/grpc/support/sync.h",
"include/grpc/support/sync_generic.h",
"include/grpc/support/sync_posix.h",
diff --git a/Makefile b/Makefile
index 32a2686f6a..b45bb9c818 100644
--- a/Makefile
+++ b/Makefile
@@ -2313,6 +2313,7 @@ LIBGPR_SRC = \
src/core/support/string.c \
src/core/support/string_posix.c \
src/core/support/string_win32.c \
+ src/core/support/subprocess_posix.c \
src/core/support/sync.c \
src/core/support/sync_posix.c \
src/core/support/sync_win32.c \
@@ -2340,6 +2341,7 @@ PUBLIC_HEADERS_C += \
include/grpc/support/port_platform.h \
include/grpc/support/slice.h \
include/grpc/support/slice_buffer.h \
+ include/grpc/support/subprocess.h \
include/grpc/support/sync.h \
include/grpc/support/sync_generic.h \
include/grpc/support/sync_posix.h \
diff --git a/build.json b/build.json
index 18591d64f8..882c3cb6ab 100644
--- a/build.json
+++ b/build.json
@@ -315,6 +315,7 @@
"include/grpc/support/port_platform.h",
"include/grpc/support/slice.h",
"include/grpc/support/slice_buffer.h",
+ "include/grpc/support/subprocess.h",
"include/grpc/support/sync.h",
"include/grpc/support/sync_generic.h",
"include/grpc/support/sync_posix.h",
@@ -362,6 +363,7 @@
"src/core/support/string.c",
"src/core/support/string_posix.c",
"src/core/support/string_win32.c",
+ "src/core/support/subprocess_posix.c",
"src/core/support/sync.c",
"src/core/support/sync_posix.c",
"src/core/support/sync_win32.c",
diff --git a/include/grpc/support/port_platform.h b/include/grpc/support/port_platform.h
index df7861c7b6..a695acf205 100644
--- a/include/grpc/support/port_platform.h
+++ b/include/grpc/support/port_platform.h
@@ -77,6 +77,7 @@
#define GPR_POSIX_ENV 1
#define GPR_POSIX_FILE 1
#define GPR_POSIX_STRING 1
+#define GPR_POSIX_SUBPROCESS 1
#define GPR_POSIX_SYNC 1
#define GPR_POSIX_TIME 1
#define GPR_GETPID_IN_UNISTD_H 1
@@ -122,6 +123,7 @@
#endif
#define GPR_POSIX_FILE 1
#define GPR_POSIX_STRING 1
+#define GPR_POSIX_SUBPROCESS 1
#define GPR_POSIX_SYNC 1
#define GPR_POSIX_TIME 1
#define GPR_GETPID_IN_UNISTD_H 1
@@ -154,6 +156,7 @@
#define GPR_POSIX_ENV 1
#define GPR_POSIX_FILE 1
#define GPR_POSIX_STRING 1
+#define GPR_POSIX_SUBPROCESS 1
#define GPR_POSIX_SYNC 1
#define GPR_POSIX_TIME 1
#define GPR_GETPID_IN_UNISTD_H 1
@@ -180,6 +183,7 @@
#define GPR_POSIX_ENV 1
#define GPR_POSIX_FILE 1
#define GPR_POSIX_STRING 1
+#define GPR_POSIX_SUBPROCESS 1
#define GPR_POSIX_SYNC 1
#define GPR_POSIX_TIME 1
#define GPR_GETPID_IN_UNISTD_H 1
diff --git a/include/grpc/support/subprocess.h b/include/grpc/support/subprocess.h
new file mode 100644
index 0000000000..c59751da83
--- /dev/null
+++ b/include/grpc/support/subprocess.h
@@ -0,0 +1,49 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GRPC_SUPPORT_SUBPROCESS_H
+#define GRPC_SUPPORT_SUBPROCESS_H
+
+typedef struct gpr_subprocess gpr_subprocess;
+
+/* .exe on windows, empty on unices */
+char *gpr_subprocess_binary_extension();
+
+gpr_subprocess *gpr_subprocess_create(int argc, char **argv);
+/* if subprocess has not been joined, kill it */
+void gpr_subprocess_destroy(gpr_subprocess *p);
+/* returns exit status; can be called at most once */
+int gpr_subprocess_join(gpr_subprocess *p);
+void gpr_subprocess_interrupt(gpr_subprocess *p);
+
+#endif
diff --git a/src/core/support/subprocess_posix.c b/src/core/support/subprocess_posix.c
new file mode 100644
index 0000000000..4580537aa8
--- /dev/null
+++ b/src/core/support/subprocess_posix.c
@@ -0,0 +1,108 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <grpc/support/port_platform.h>
+
+#ifdef GPR_POSIX_SUBPROCESS
+
+#include <grpc/support/subprocess.h>
+
+#include <unistd.h>
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+
+struct gpr_subprocess {
+ int pid;
+ int joined;
+};
+
+char *gpr_subprocess_binary_extension() { return ""; }
+
+gpr_subprocess *gpr_subprocess_create(int argc, char **argv) {
+ gpr_subprocess *r;
+ int pid;
+ char **exec_args;
+
+ pid = fork();
+ if (pid == -1) {
+ return NULL;
+ } else if (pid == 0) {
+ exec_args = gpr_malloc((argc + 1) * sizeof(char *));
+ memcpy(exec_args, argv, 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_malloc(sizeof(gpr_subprocess));
+ memset(r, 0, sizeof(*r));
+ 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;
+ if (waitpid(p->pid, &status, 0) == -1) {
+ gpr_log(GPR_ERROR, "waitpid failed: %s", strerror(errno));
+ return -1;
+ }
+ return status;
+}
+
+void gpr_subprocess_interrupt(gpr_subprocess *p) {
+ if (!p->joined) {
+ kill(p->pid, SIGINT);
+ }
+}
+
+#endif /* GPR_POSIX_SUBPROCESS */
diff --git a/test/core/fling/fling_test.c b/test/core/fling/fling_test.c
index c0066cf101..7c1643df6a 100644
--- a/test/core/fling/fling_test.c
+++ b/test/core/fling/fling_test.c
@@ -31,20 +31,11 @@
*
*/
-#ifndef _POSIX_SOURCE
-#define _POSIX_SOURCE
-#endif
-
-#include <unistd.h>
-#include <assert.h>
-#include <stdio.h>
#include <string.h>
-#include <signal.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/wait.h>
+#include <stdio.h>
#include <grpc/support/alloc.h>
+#include <grpc/support/subprocess.h>
#include <grpc/support/host_port.h>
#include "src/core/support/string.h"
#include "test/core/util/port.h"
@@ -56,10 +47,7 @@ int main(int argc, char **argv) {
int port = grpc_pick_unused_port_or_die();
char *args[10];
int status;
- pid_t svr, cli;
- /* seed rng with pid, so we don't end up with the same random numbers as a
- concurrently running test binary */
- srand(getpid());
+ gpr_subprocess *svr, *cli;
/* figure out where we are */
if (lslash) {
memcpy(root, me, lslash - me);
@@ -68,45 +56,36 @@ int main(int argc, char **argv) {
strcpy(root, ".");
}
/* start the server */
- svr = fork();
- if (svr == 0) {
- gpr_asprintf(&args[0], "%s/fling_server", root);
- args[1] = "--bind";
- gpr_join_host_port(&args[2], "::", port);
- args[3] = "--no-secure";
- args[4] = 0;
- execv(args[0], args);
+ gpr_asprintf(&args[0], "%s/fling_server%s", root, gpr_subprocess_binary_extension());
+ args[1] = "--bind";
+ gpr_join_host_port(&args[2], "::", port);
+ args[3] = "--no-secure";
+ svr = gpr_subprocess_create(4, args);
+ gpr_free(args[0]);
+ gpr_free(args[2]);
- gpr_free(args[0]);
- gpr_free(args[2]);
- return 1;
- }
- /* wait a little */
- sleep(2);
/* start the client */
- cli = fork();
- if (cli == 0) {
- gpr_asprintf(&args[0], "%s/fling_client", root);
- args[1] = "--target";
- gpr_join_host_port(&args[2], "127.0.0.1", port);
- args[3] = "--scenario=ping-pong-request";
- args[4] = "--no-secure";
- args[5] = 0;
- execv(args[0], args);
+ gpr_asprintf(&args[0], "%s/fling_client%s", root, gpr_subprocess_binary_extension());
+ args[1] = "--target";
+ gpr_join_host_port(&args[2], "127.0.0.1", port);
+ args[3] = "--scenario=ping-pong-request";
+ args[4] = "--no-secure";
+ args[5] = 0;
+ cli = gpr_subprocess_create(6, args);
+ gpr_free(args[0]);
+ gpr_free(args[2]);
- gpr_free(args[0]);
- gpr_free(args[2]);
- return 1;
- }
/* wait for completion */
printf("waiting for client\n");
- if (waitpid(cli, &status, 0) == -1) return 2;
- if (!WIFEXITED(status)) return 4;
- if (WEXITSTATUS(status)) return WEXITSTATUS(status);
- printf("waiting for server\n");
- kill(svr, SIGINT);
- if (waitpid(svr, &status, 0) == -1) return 2;
- if (!WIFEXITED(status)) return 4;
- if (WEXITSTATUS(status)) return WEXITSTATUS(status);
- return 0;
+ if ((status = gpr_subprocess_join(cli))) {
+ gpr_subprocess_destroy(cli);
+ gpr_subprocess_destroy(svr);
+ return status;
+ }
+ gpr_subprocess_destroy(cli);
+
+ gpr_subprocess_interrupt(svr);
+ status = gpr_subprocess_join(svr);
+ gpr_subprocess_destroy(svr);
+ return status;
}
diff --git a/vsprojects/gpr/gpr.vcxproj b/vsprojects/gpr/gpr.vcxproj
index 6b81aaaf73..a7e7c2754f 100644
--- a/vsprojects/gpr/gpr.vcxproj
+++ b/vsprojects/gpr/gpr.vcxproj
@@ -161,6 +161,7 @@
<ClInclude Include="..\..\include\grpc\support\port_platform.h" />
<ClInclude Include="..\..\include\grpc\support\slice.h" />
<ClInclude Include="..\..\include\grpc\support\slice_buffer.h" />
+ <ClInclude Include="..\..\include\grpc\support\subprocess.h" />
<ClInclude Include="..\..\include\grpc\support\sync.h" />
<ClInclude Include="..\..\include\grpc\support\sync_generic.h" />
<ClInclude Include="..\..\include\grpc\support\sync_posix.h" />
@@ -234,6 +235,8 @@
</ClCompile>
<ClCompile Include="..\..\src\core\support\string_win32.c">
</ClCompile>
+ <ClCompile Include="..\..\src\core\support\subprocess_posix.c">
+ </ClCompile>
<ClCompile Include="..\..\src\core\support\sync.c">
</ClCompile>
<ClCompile Include="..\..\src\core\support\sync_posix.c">
diff --git a/vsprojects/gpr/gpr.vcxproj.filters b/vsprojects/gpr/gpr.vcxproj.filters
index 41b30384a0..0f81ef598a 100644
--- a/vsprojects/gpr/gpr.vcxproj.filters
+++ b/vsprojects/gpr/gpr.vcxproj.filters
@@ -79,6 +79,9 @@
<ClCompile Include="..\..\src\core\support\string_win32.c">
<Filter>src\core\support</Filter>
</ClCompile>
+ <ClCompile Include="..\..\src\core\support\subprocess_posix.c">
+ <Filter>src\core\support</Filter>
+ </ClCompile>
<ClCompile Include="..\..\src\core\support\sync.c">
<Filter>src\core\support</Filter>
</ClCompile>
@@ -156,6 +159,9 @@
<ClInclude Include="..\..\include\grpc\support\slice_buffer.h">
<Filter>include\grpc\support</Filter>
</ClInclude>
+ <ClInclude Include="..\..\include\grpc\support\subprocess.h">
+ <Filter>include\grpc\support</Filter>
+ </ClInclude>
<ClInclude Include="..\..\include\grpc\support\sync.h">
<Filter>include\grpc\support</Filter>
</ClInclude>