aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--BUILD4
-rw-r--r--CMakeLists.txt32
-rw-r--r--Makefile38
-rw-r--r--build.yaml16
-rw-r--r--config.m42
-rw-r--r--config.w322
-rw-r--r--gRPC-C++.podspec4
-rw-r--r--gRPC-Core.podspec6
-rw-r--r--grpc.gemspec4
-rw-r--r--grpc.gyp2
-rw-r--r--package.xml4
-rw-r--r--src/core/lib/gpr/fork.cc78
-rw-r--r--src/core/lib/gpr/fork.h35
-rw-r--r--src/core/lib/gprpp/fork.cc256
-rw-r--r--src/core/lib/gprpp/fork.h79
-rw-r--r--src/core/lib/gprpp/thd.h3
-rw-r--r--src/core/lib/gprpp/thd_posix.cc57
-rw-r--r--src/core/lib/gprpp/thd_windows.cc7
-rw-r--r--src/core/lib/iomgr/exec_ctx.h12
-rw-r--r--src/core/lib/iomgr/fork_posix.cc47
-rw-r--r--src/core/lib/surface/init.cc9
-rw-r--r--src/python/grpcio/grpc_core_dependencies.py2
-rw-r--r--test/core/gprpp/BUILD10
-rw-r--r--test/core/gprpp/fork_test.cc136
-rw-r--r--tools/doxygen/Doxyfile.c++.internal2
-rw-r--r--tools/doxygen/Doxyfile.core.internal4
-rw-r--r--tools/run_tests/generated/sources_and_headers.json21
-rw-r--r--tools/run_tests/generated/tests.json20
28 files changed, 667 insertions, 225 deletions
diff --git a/BUILD b/BUILD
index c35a7d65e1..4c99052e05 100644
--- a/BUILD
+++ b/BUILD
@@ -512,7 +512,6 @@ grpc_cc_library(
"src/core/lib/gpr/env_linux.cc",
"src/core/lib/gpr/env_posix.cc",
"src/core/lib/gpr/env_windows.cc",
- "src/core/lib/gpr/fork.cc",
"src/core/lib/gpr/host_port.cc",
"src/core/lib/gpr/log.cc",
"src/core/lib/gpr/log_android.cc",
@@ -537,6 +536,7 @@ grpc_cc_library(
"src/core/lib/gpr/tmpfile_posix.cc",
"src/core/lib/gpr/tmpfile_windows.cc",
"src/core/lib/gpr/wrap_memcpy.cc",
+ "src/core/lib/gprpp/fork.cc",
"src/core/lib/gprpp/thd_posix.cc",
"src/core/lib/gprpp/thd_windows.cc",
"src/core/lib/profiling/basic_timers.cc",
@@ -545,7 +545,6 @@ grpc_cc_library(
hdrs = [
"src/core/lib/gpr/arena.h",
"src/core/lib/gpr/env.h",
- "src/core/lib/gpr/fork.h",
"src/core/lib/gpr/host_port.h",
"src/core/lib/gpr/mpscq.h",
"src/core/lib/gpr/murmur_hash.h",
@@ -560,6 +559,7 @@ grpc_cc_library(
"src/core/lib/gpr/tmpfile.h",
"src/core/lib/gpr/useful.h",
"src/core/lib/gprpp/abstract.h",
+ "src/core/lib/gprpp/fork.h",
"src/core/lib/gprpp/manual_constructor.h",
"src/core/lib/gprpp/memory.h",
"src/core/lib/gprpp/thd.h",
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 93f51e79eb..d1933c4b04 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -264,6 +264,9 @@ endif()
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_dependencies(buildtests_c fling_test)
endif()
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC)
+add_dependencies(buildtests_c fork_test)
+endif()
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_dependencies(buildtests_c goaway_server_test)
endif()
@@ -760,7 +763,6 @@ add_library(gpr
src/core/lib/gpr/env_linux.cc
src/core/lib/gpr/env_posix.cc
src/core/lib/gpr/env_windows.cc
- src/core/lib/gpr/fork.cc
src/core/lib/gpr/host_port.cc
src/core/lib/gpr/log.cc
src/core/lib/gpr/log_android.cc
@@ -785,6 +787,7 @@ add_library(gpr
src/core/lib/gpr/tmpfile_posix.cc
src/core/lib/gpr/tmpfile_windows.cc
src/core/lib/gpr/wrap_memcpy.cc
+ src/core/lib/gprpp/fork.cc
src/core/lib/gprpp/thd_posix.cc
src/core/lib/gprpp/thd_windows.cc
src/core/lib/profiling/basic_timers.cc
@@ -6415,6 +6418,33 @@ target_link_libraries(fling_test
endif()
endif (gRPC_BUILD_TESTS)
if (gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC)
+
+add_executable(fork_test
+ test/core/gprpp/fork_test.cc
+)
+
+
+target_include_directories(fork_test
+ PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
+ PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
+ PRIVATE ${_gRPC_SSL_INCLUDE_DIR}
+ PRIVATE ${_gRPC_PROTOBUF_INCLUDE_DIR}
+ PRIVATE ${_gRPC_ZLIB_INCLUDE_DIR}
+ PRIVATE ${_gRPC_BENCHMARK_INCLUDE_DIR}
+ PRIVATE ${_gRPC_CARES_INCLUDE_DIR}
+ PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR}
+)
+
+target_link_libraries(fork_test
+ ${_gRPC_ALLTARGETS_LIBRARIES}
+ gpr_test_util
+ gpr
+)
+
+endif()
+endif (gRPC_BUILD_TESTS)
+if (gRPC_BUILD_TESTS)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_executable(goaway_server_test
diff --git a/Makefile b/Makefile
index ba765f0af6..18663c7266 100644
--- a/Makefile
+++ b/Makefile
@@ -993,6 +993,7 @@ fling_client: $(BINDIR)/$(CONFIG)/fling_client
fling_server: $(BINDIR)/$(CONFIG)/fling_server
fling_stream_test: $(BINDIR)/$(CONFIG)/fling_stream_test
fling_test: $(BINDIR)/$(CONFIG)/fling_test
+fork_test: $(BINDIR)/$(CONFIG)/fork_test
goaway_server_test: $(BINDIR)/$(CONFIG)/goaway_server_test
gpr_cpu_test: $(BINDIR)/$(CONFIG)/gpr_cpu_test
gpr_env_test: $(BINDIR)/$(CONFIG)/gpr_env_test
@@ -1435,6 +1436,7 @@ buildtests_c: privatelibs_c \
$(BINDIR)/$(CONFIG)/fling_server \
$(BINDIR)/$(CONFIG)/fling_stream_test \
$(BINDIR)/$(CONFIG)/fling_test \
+ $(BINDIR)/$(CONFIG)/fork_test \
$(BINDIR)/$(CONFIG)/goaway_server_test \
$(BINDIR)/$(CONFIG)/gpr_cpu_test \
$(BINDIR)/$(CONFIG)/gpr_env_test \
@@ -1954,6 +1956,8 @@ test_c: buildtests_c
$(Q) $(BINDIR)/$(CONFIG)/fling_stream_test || ( echo test fling_stream_test failed ; exit 1 )
$(E) "[RUN] Testing fling_test"
$(Q) $(BINDIR)/$(CONFIG)/fling_test || ( echo test fling_test failed ; exit 1 )
+ $(E) "[RUN] Testing fork_test"
+ $(Q) $(BINDIR)/$(CONFIG)/fork_test || ( echo test fork_test failed ; exit 1 )
$(E) "[RUN] Testing goaway_server_test"
$(Q) $(BINDIR)/$(CONFIG)/goaway_server_test || ( echo test goaway_server_test failed ; exit 1 )
$(E) "[RUN] Testing gpr_cpu_test"
@@ -3176,7 +3180,6 @@ LIBGPR_SRC = \
src/core/lib/gpr/env_linux.cc \
src/core/lib/gpr/env_posix.cc \
src/core/lib/gpr/env_windows.cc \
- src/core/lib/gpr/fork.cc \
src/core/lib/gpr/host_port.cc \
src/core/lib/gpr/log.cc \
src/core/lib/gpr/log_android.cc \
@@ -3201,6 +3204,7 @@ LIBGPR_SRC = \
src/core/lib/gpr/tmpfile_posix.cc \
src/core/lib/gpr/tmpfile_windows.cc \
src/core/lib/gpr/wrap_memcpy.cc \
+ src/core/lib/gprpp/fork.cc \
src/core/lib/gprpp/thd_posix.cc \
src/core/lib/gprpp/thd_windows.cc \
src/core/lib/profiling/basic_timers.cc \
@@ -11293,6 +11297,38 @@ endif
endif
+FORK_TEST_SRC = \
+ test/core/gprpp/fork_test.cc \
+
+FORK_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(FORK_TEST_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/fork_test: openssl_dep_error
+
+else
+
+
+
+$(BINDIR)/$(CONFIG)/fork_test: $(FORK_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+ $(E) "[LD] Linking $@"
+ $(Q) mkdir -p `dirname $@`
+ $(Q) $(LD) $(LDFLAGS) $(FORK_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/fork_test
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/gprpp/fork_test.o: $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_fork_test: $(FORK_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(FORK_TEST_OBJS:.o=.dep)
+endif
+endif
+
+
GOAWAY_SERVER_TEST_SRC = \
test/core/end2end/goaway_server_test.cc \
diff --git a/build.yaml b/build.yaml
index 1bc2adbb8c..f4812aa538 100644
--- a/build.yaml
+++ b/build.yaml
@@ -123,7 +123,6 @@ filegroups:
- src/core/lib/gpr/env_linux.cc
- src/core/lib/gpr/env_posix.cc
- src/core/lib/gpr/env_windows.cc
- - src/core/lib/gpr/fork.cc
- src/core/lib/gpr/host_port.cc
- src/core/lib/gpr/log.cc
- src/core/lib/gpr/log_android.cc
@@ -148,6 +147,7 @@ filegroups:
- src/core/lib/gpr/tmpfile_posix.cc
- src/core/lib/gpr/tmpfile_windows.cc
- src/core/lib/gpr/wrap_memcpy.cc
+ - src/core/lib/gprpp/fork.cc
- src/core/lib/gprpp/thd_posix.cc
- src/core/lib/gprpp/thd_windows.cc
- src/core/lib/profiling/basic_timers.cc
@@ -176,7 +176,6 @@ filegroups:
headers:
- src/core/lib/gpr/arena.h
- src/core/lib/gpr/env.h
- - src/core/lib/gpr/fork.h
- src/core/lib/gpr/host_port.h
- src/core/lib/gpr/mpscq.h
- src/core/lib/gpr/murmur_hash.h
@@ -194,6 +193,7 @@ filegroups:
- src/core/lib/gprpp/atomic.h
- src/core/lib/gprpp/atomic_with_atm.h
- src/core/lib/gprpp/atomic_with_std.h
+ - src/core/lib/gprpp/fork.h
- src/core/lib/gprpp/manual_constructor.h
- src/core/lib/gprpp/memory.h
- src/core/lib/gprpp/thd.h
@@ -2387,6 +2387,18 @@ targets:
- mac
- linux
- posix
+- name: fork_test
+ build: test
+ language: c
+ src:
+ - test/core/gprpp/fork_test.cc
+ deps:
+ - gpr_test_util
+ - gpr
+ platforms:
+ - mac
+ - linux
+ uses_polling: false
- name: goaway_server_test
cpu_cost: 0.1
build: test
diff --git a/config.m4 b/config.m4
index ee2aca4fa5..3acc72eaa1 100644
--- a/config.m4
+++ b/config.m4
@@ -53,7 +53,6 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/gpr/env_linux.cc \
src/core/lib/gpr/env_posix.cc \
src/core/lib/gpr/env_windows.cc \
- src/core/lib/gpr/fork.cc \
src/core/lib/gpr/host_port.cc \
src/core/lib/gpr/log.cc \
src/core/lib/gpr/log_android.cc \
@@ -78,6 +77,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/lib/gpr/tmpfile_posix.cc \
src/core/lib/gpr/tmpfile_windows.cc \
src/core/lib/gpr/wrap_memcpy.cc \
+ src/core/lib/gprpp/fork.cc \
src/core/lib/gprpp/thd_posix.cc \
src/core/lib/gprpp/thd_windows.cc \
src/core/lib/profiling/basic_timers.cc \
diff --git a/config.w32 b/config.w32
index abca8e22f2..d1a595026f 100644
--- a/config.w32
+++ b/config.w32
@@ -29,7 +29,6 @@ if (PHP_GRPC != "no") {
"src\\core\\lib\\gpr\\env_linux.cc " +
"src\\core\\lib\\gpr\\env_posix.cc " +
"src\\core\\lib\\gpr\\env_windows.cc " +
- "src\\core\\lib\\gpr\\fork.cc " +
"src\\core\\lib\\gpr\\host_port.cc " +
"src\\core\\lib\\gpr\\log.cc " +
"src\\core\\lib\\gpr\\log_android.cc " +
@@ -54,6 +53,7 @@ if (PHP_GRPC != "no") {
"src\\core\\lib\\gpr\\tmpfile_posix.cc " +
"src\\core\\lib\\gpr\\tmpfile_windows.cc " +
"src\\core\\lib\\gpr\\wrap_memcpy.cc " +
+ "src\\core\\lib\\gprpp\\fork.cc " +
"src\\core\\lib\\gprpp\\thd_posix.cc " +
"src\\core\\lib\\gprpp\\thd_windows.cc " +
"src\\core\\lib\\profiling\\basic_timers.cc " +
diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec
index 29b79e0b01..0b15bb8532 100644
--- a/gRPC-C++.podspec
+++ b/gRPC-C++.podspec
@@ -214,7 +214,6 @@ Pod::Spec.new do |s|
'src/cpp/codegen/codegen_init.cc',
'src/core/lib/gpr/arena.h',
'src/core/lib/gpr/env.h',
- 'src/core/lib/gpr/fork.h',
'src/core/lib/gpr/host_port.h',
'src/core/lib/gpr/mpscq.h',
'src/core/lib/gpr/murmur_hash.h',
@@ -232,6 +231,7 @@ Pod::Spec.new do |s|
'src/core/lib/gprpp/atomic.h',
'src/core/lib/gprpp/atomic_with_atm.h',
'src/core/lib/gprpp/atomic_with_std.h',
+ 'src/core/lib/gprpp/fork.h',
'src/core/lib/gprpp/manual_constructor.h',
'src/core/lib/gprpp/memory.h',
'src/core/lib/gprpp/thd.h',
@@ -504,7 +504,6 @@ Pod::Spec.new do |s|
'src/cpp/thread_manager/thread_manager.h',
'src/core/lib/gpr/arena.h',
'src/core/lib/gpr/env.h',
- 'src/core/lib/gpr/fork.h',
'src/core/lib/gpr/host_port.h',
'src/core/lib/gpr/mpscq.h',
'src/core/lib/gpr/murmur_hash.h',
@@ -522,6 +521,7 @@ Pod::Spec.new do |s|
'src/core/lib/gprpp/atomic.h',
'src/core/lib/gprpp/atomic_with_atm.h',
'src/core/lib/gprpp/atomic_with_std.h',
+ 'src/core/lib/gprpp/fork.h',
'src/core/lib/gprpp/manual_constructor.h',
'src/core/lib/gprpp/memory.h',
'src/core/lib/gprpp/thd.h',
diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec
index ce6ff76806..89cc95fccd 100644
--- a/gRPC-Core.podspec
+++ b/gRPC-Core.podspec
@@ -185,7 +185,6 @@ Pod::Spec.new do |s|
# To save you from scrolling, this is the last part of the podspec.
ss.source_files = 'src/core/lib/gpr/arena.h',
'src/core/lib/gpr/env.h',
- 'src/core/lib/gpr/fork.h',
'src/core/lib/gpr/host_port.h',
'src/core/lib/gpr/mpscq.h',
'src/core/lib/gpr/murmur_hash.h',
@@ -203,6 +202,7 @@ Pod::Spec.new do |s|
'src/core/lib/gprpp/atomic.h',
'src/core/lib/gprpp/atomic_with_atm.h',
'src/core/lib/gprpp/atomic_with_std.h',
+ 'src/core/lib/gprpp/fork.h',
'src/core/lib/gprpp/manual_constructor.h',
'src/core/lib/gprpp/memory.h',
'src/core/lib/gprpp/thd.h',
@@ -217,7 +217,6 @@ Pod::Spec.new do |s|
'src/core/lib/gpr/env_linux.cc',
'src/core/lib/gpr/env_posix.cc',
'src/core/lib/gpr/env_windows.cc',
- 'src/core/lib/gpr/fork.cc',
'src/core/lib/gpr/host_port.cc',
'src/core/lib/gpr/log.cc',
'src/core/lib/gpr/log_android.cc',
@@ -242,6 +241,7 @@ Pod::Spec.new do |s|
'src/core/lib/gpr/tmpfile_posix.cc',
'src/core/lib/gpr/tmpfile_windows.cc',
'src/core/lib/gpr/wrap_memcpy.cc',
+ 'src/core/lib/gprpp/fork.cc',
'src/core/lib/gprpp/thd_posix.cc',
'src/core/lib/gprpp/thd_windows.cc',
'src/core/lib/profiling/basic_timers.cc',
@@ -802,7 +802,6 @@ Pod::Spec.new do |s|
ss.private_header_files = 'src/core/lib/gpr/arena.h',
'src/core/lib/gpr/env.h',
- 'src/core/lib/gpr/fork.h',
'src/core/lib/gpr/host_port.h',
'src/core/lib/gpr/mpscq.h',
'src/core/lib/gpr/murmur_hash.h',
@@ -820,6 +819,7 @@ Pod::Spec.new do |s|
'src/core/lib/gprpp/atomic.h',
'src/core/lib/gprpp/atomic_with_atm.h',
'src/core/lib/gprpp/atomic_with_std.h',
+ 'src/core/lib/gprpp/fork.h',
'src/core/lib/gprpp/manual_constructor.h',
'src/core/lib/gprpp/memory.h',
'src/core/lib/gprpp/thd.h',
diff --git a/grpc.gemspec b/grpc.gemspec
index 2a66801e34..80422ac670 100644
--- a/grpc.gemspec
+++ b/grpc.gemspec
@@ -81,7 +81,6 @@ Gem::Specification.new do |s|
s.files += %w( include/grpc/impl/codegen/sync_windows.h )
s.files += %w( src/core/lib/gpr/arena.h )
s.files += %w( src/core/lib/gpr/env.h )
- s.files += %w( src/core/lib/gpr/fork.h )
s.files += %w( src/core/lib/gpr/host_port.h )
s.files += %w( src/core/lib/gpr/mpscq.h )
s.files += %w( src/core/lib/gpr/murmur_hash.h )
@@ -99,6 +98,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/gprpp/atomic.h )
s.files += %w( src/core/lib/gprpp/atomic_with_atm.h )
s.files += %w( src/core/lib/gprpp/atomic_with_std.h )
+ s.files += %w( src/core/lib/gprpp/fork.h )
s.files += %w( src/core/lib/gprpp/manual_constructor.h )
s.files += %w( src/core/lib/gprpp/memory.h )
s.files += %w( src/core/lib/gprpp/thd.h )
@@ -113,7 +113,6 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/gpr/env_linux.cc )
s.files += %w( src/core/lib/gpr/env_posix.cc )
s.files += %w( src/core/lib/gpr/env_windows.cc )
- s.files += %w( src/core/lib/gpr/fork.cc )
s.files += %w( src/core/lib/gpr/host_port.cc )
s.files += %w( src/core/lib/gpr/log.cc )
s.files += %w( src/core/lib/gpr/log_android.cc )
@@ -138,6 +137,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/lib/gpr/tmpfile_posix.cc )
s.files += %w( src/core/lib/gpr/tmpfile_windows.cc )
s.files += %w( src/core/lib/gpr/wrap_memcpy.cc )
+ s.files += %w( src/core/lib/gprpp/fork.cc )
s.files += %w( src/core/lib/gprpp/thd_posix.cc )
s.files += %w( src/core/lib/gprpp/thd_windows.cc )
s.files += %w( src/core/lib/profiling/basic_timers.cc )
diff --git a/grpc.gyp b/grpc.gyp
index 5726719521..0d03a66b75 100644
--- a/grpc.gyp
+++ b/grpc.gyp
@@ -194,7 +194,6 @@
'src/core/lib/gpr/env_linux.cc',
'src/core/lib/gpr/env_posix.cc',
'src/core/lib/gpr/env_windows.cc',
- 'src/core/lib/gpr/fork.cc',
'src/core/lib/gpr/host_port.cc',
'src/core/lib/gpr/log.cc',
'src/core/lib/gpr/log_android.cc',
@@ -219,6 +218,7 @@
'src/core/lib/gpr/tmpfile_posix.cc',
'src/core/lib/gpr/tmpfile_windows.cc',
'src/core/lib/gpr/wrap_memcpy.cc',
+ 'src/core/lib/gprpp/fork.cc',
'src/core/lib/gprpp/thd_posix.cc',
'src/core/lib/gprpp/thd_windows.cc',
'src/core/lib/profiling/basic_timers.cc',
diff --git a/package.xml b/package.xml
index ac9b520fb7..4e8d514883 100644
--- a/package.xml
+++ b/package.xml
@@ -88,7 +88,6 @@
<file baseinstalldir="/" name="include/grpc/impl/codegen/sync_windows.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/gpr/arena.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/gpr/env.h" role="src" />
- <file baseinstalldir="/" name="src/core/lib/gpr/fork.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/gpr/host_port.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/gpr/mpscq.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/gpr/murmur_hash.h" role="src" />
@@ -106,6 +105,7 @@
<file baseinstalldir="/" name="src/core/lib/gprpp/atomic.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/gprpp/atomic_with_atm.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/gprpp/atomic_with_std.h" role="src" />
+ <file baseinstalldir="/" name="src/core/lib/gprpp/fork.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/gprpp/manual_constructor.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/gprpp/memory.h" role="src" />
<file baseinstalldir="/" name="src/core/lib/gprpp/thd.h" role="src" />
@@ -120,7 +120,6 @@
<file baseinstalldir="/" name="src/core/lib/gpr/env_linux.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/gpr/env_posix.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/gpr/env_windows.cc" role="src" />
- <file baseinstalldir="/" name="src/core/lib/gpr/fork.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/gpr/host_port.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/gpr/log.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/gpr/log_android.cc" role="src" />
@@ -145,6 +144,7 @@
<file baseinstalldir="/" name="src/core/lib/gpr/tmpfile_posix.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/gpr/tmpfile_windows.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/gpr/wrap_memcpy.cc" role="src" />
+ <file baseinstalldir="/" name="src/core/lib/gprpp/fork.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/gprpp/thd_posix.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/gprpp/thd_windows.cc" role="src" />
<file baseinstalldir="/" name="src/core/lib/profiling/basic_timers.cc" role="src" />
diff --git a/src/core/lib/gpr/fork.cc b/src/core/lib/gpr/fork.cc
deleted file mode 100644
index 812522b058..0000000000
--- a/src/core/lib/gpr/fork.cc
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- *
- * Copyright 2017 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 <grpc/support/port_platform.h>
-
-#include "src/core/lib/gpr/fork.h"
-
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-
-#include "src/core/lib/gpr/env.h"
-#include "src/core/lib/gpr/useful.h"
-
-/*
- * NOTE: FORKING IS NOT GENERALLY SUPPORTED, THIS IS ONLY INTENDED TO WORK
- * AROUND VERY SPECIFIC USE CASES.
- */
-
-static int override_fork_support_enabled = -1;
-static int fork_support_enabled;
-
-void grpc_fork_support_init() {
-#ifdef GRPC_ENABLE_FORK_SUPPORT
- fork_support_enabled = 1;
-#else
- fork_support_enabled = 0;
-#endif
- bool env_var_set = false;
- char* env = gpr_getenv("GRPC_ENABLE_FORK_SUPPORT");
- if (env != nullptr) {
- static const char* truthy[] = {"yes", "Yes", "YES", "true",
- "True", "TRUE", "1"};
- static const char* falsey[] = {"no", "No", "NO", "false",
- "False", "FALSE", "0"};
- for (size_t i = 0; i < GPR_ARRAY_SIZE(truthy); i++) {
- if (0 == strcmp(env, truthy[i])) {
- fork_support_enabled = 1;
- env_var_set = true;
- break;
- }
- }
- if (!env_var_set) {
- for (size_t i = 0; i < GPR_ARRAY_SIZE(falsey); i++) {
- if (0 == strcmp(env, falsey[i])) {
- fork_support_enabled = 0;
- env_var_set = true;
- break;
- }
- }
- }
- gpr_free(env);
- }
- if (override_fork_support_enabled != -1) {
- fork_support_enabled = override_fork_support_enabled;
- }
-}
-
-int grpc_fork_support_enabled() { return fork_support_enabled; }
-
-void grpc_enable_fork_support(int enable) {
- override_fork_support_enabled = enable;
-}
diff --git a/src/core/lib/gpr/fork.h b/src/core/lib/gpr/fork.h
deleted file mode 100644
index 94c61bb836..0000000000
--- a/src/core/lib/gpr/fork.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- *
- * Copyright 2017 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.
- *
- */
-
-#ifndef GRPC_CORE_LIB_GPR_FORK_H
-#define GRPC_CORE_LIB_GPR_FORK_H
-
-/*
- * NOTE: FORKING IS NOT GENERALLY SUPPORTED, THIS IS ONLY INTENDED TO WORK
- * AROUND VERY SPECIFIC USE CASES.
- */
-
-void grpc_fork_support_init(void);
-
-int grpc_fork_support_enabled(void);
-
-// Test only: Must be called before grpc_init(), and overrides
-// environment variables/compile flags
-void grpc_enable_fork_support(int enable);
-
-#endif /* GRPC_CORE_LIB_GPR_FORK_H */
diff --git a/src/core/lib/gprpp/fork.cc b/src/core/lib/gprpp/fork.cc
new file mode 100644
index 0000000000..ddc95f26eb
--- /dev/null
+++ b/src/core/lib/gprpp/fork.cc
@@ -0,0 +1,256 @@
+/*
+ *
+ * Copyright 2017 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 <grpc/support/port_platform.h>
+
+#include "src/core/lib/gprpp/fork.h"
+
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/sync.h>
+#include <grpc/support/time.h>
+
+#include "src/core/lib/gpr/env.h"
+#include "src/core/lib/gpr/useful.h"
+#include "src/core/lib/gprpp/memory.h"
+
+/*
+ * NOTE: FORKING IS NOT GENERALLY SUPPORTED, THIS IS ONLY INTENDED TO WORK
+ * AROUND VERY SPECIFIC USE CASES.
+ */
+
+namespace grpc_core {
+namespace internal {
+// The exec_ctx_count has 2 modes, blocked and unblocked.
+// When unblocked, the count is 2-indexed; exec_ctx_count=2 indicates
+// 0 active ExecCtxs, exex_ctx_count=3 indicates 1 active ExecCtxs...
+
+// When blocked, the exec_ctx_count is 0-indexed. Note that ExecCtx
+// creation can only be blocked if there is exactly 1 outstanding ExecCtx,
+// meaning that BLOCKED and UNBLOCKED counts partition the integers
+#define UNBLOCKED(n) (n + 2)
+#define BLOCKED(n) (n)
+
+class ExecCtxState {
+ public:
+ ExecCtxState() : fork_complete_(true) {
+ gpr_mu_init(&mu_);
+ gpr_cv_init(&cv_);
+ gpr_atm_no_barrier_store(&count_, UNBLOCKED(0));
+ }
+
+ void IncExecCtxCount() {
+ intptr_t count = static_cast<intptr_t>(gpr_atm_no_barrier_load(&count_));
+ while (true) {
+ if (count <= BLOCKED(1)) {
+ // This only occurs if we are trying to fork. Wait until the fork()
+ // operation completes before allowing new ExecCtxs.
+ gpr_mu_lock(&mu_);
+ if (gpr_atm_no_barrier_load(&count_) <= BLOCKED(1)) {
+ while (!fork_complete_) {
+ gpr_cv_wait(&cv_, &mu_, gpr_inf_future(GPR_CLOCK_REALTIME));
+ }
+ }
+ gpr_mu_unlock(&mu_);
+ } else if (gpr_atm_no_barrier_cas(&count_, count, count + 1)) {
+ break;
+ }
+ count = gpr_atm_no_barrier_load(&count_);
+ }
+ }
+
+ void DecExecCtxCount() { gpr_atm_no_barrier_fetch_add(&count_, -1); }
+
+ bool BlockExecCtx() {
+ // Assumes there is an active ExecCtx when this function is called
+ if (gpr_atm_no_barrier_cas(&count_, UNBLOCKED(1), BLOCKED(1))) {
+ fork_complete_ = false;
+ return true;
+ }
+ return false;
+ }
+
+ void AllowExecCtx() {
+ gpr_mu_lock(&mu_);
+ gpr_atm_no_barrier_store(&count_, UNBLOCKED(0));
+ fork_complete_ = true;
+ gpr_cv_broadcast(&cv_);
+ gpr_mu_unlock(&mu_);
+ }
+
+ ~ExecCtxState() {
+ gpr_mu_destroy(&mu_);
+ gpr_cv_destroy(&cv_);
+ }
+
+ private:
+ bool fork_complete_;
+ gpr_mu mu_;
+ gpr_cv cv_;
+ gpr_atm count_;
+};
+
+class ThreadState {
+ public:
+ ThreadState() : awaiting_threads_(false), threads_done_(false), count_(0) {
+ gpr_mu_init(&mu_);
+ gpr_cv_init(&cv_);
+ }
+
+ void IncThreadCount() {
+ gpr_mu_lock(&mu_);
+ count_++;
+ gpr_mu_unlock(&mu_);
+ }
+
+ void DecThreadCount() {
+ gpr_mu_lock(&mu_);
+ count_--;
+ if (awaiting_threads_ && count_ == 0) {
+ threads_done_ = true;
+ gpr_cv_signal(&cv_);
+ }
+ gpr_mu_unlock(&mu_);
+ }
+ void AwaitThreads() {
+ gpr_mu_lock(&mu_);
+ awaiting_threads_ = true;
+ threads_done_ = (count_ == 0);
+ while (!threads_done_) {
+ gpr_cv_wait(&cv_, &mu_, gpr_inf_future(GPR_CLOCK_REALTIME));
+ }
+ awaiting_threads_ = true;
+ gpr_mu_unlock(&mu_);
+ }
+
+ ~ThreadState() {
+ gpr_mu_destroy(&mu_);
+ gpr_cv_destroy(&cv_);
+ }
+
+ private:
+ bool awaiting_threads_;
+ bool threads_done_;
+ gpr_mu mu_;
+ gpr_cv cv_;
+ int count_;
+};
+
+} // namespace
+
+void Fork::GlobalInit() {
+#ifdef GRPC_ENABLE_FORK_SUPPORT
+ supportEnabled_ = true;
+#else
+ supportEnabled_ = false;
+#endif
+ bool env_var_set = false;
+ char* env = gpr_getenv("GRPC_ENABLE_FORK_SUPPORT");
+ if (env != nullptr) {
+ static const char* truthy[] = {"yes", "Yes", "YES", "true",
+ "True", "TRUE", "1"};
+ static const char* falsey[] = {"no", "No", "NO", "false",
+ "False", "FALSE", "0"};
+ for (size_t i = 0; i < GPR_ARRAY_SIZE(truthy); i++) {
+ if (0 == strcmp(env, truthy[i])) {
+ supportEnabled_ = true;
+ env_var_set = true;
+ break;
+ }
+ }
+ if (!env_var_set) {
+ for (size_t i = 0; i < GPR_ARRAY_SIZE(falsey); i++) {
+ if (0 == strcmp(env, falsey[i])) {
+ supportEnabled_ = false;
+ env_var_set = true;
+ break;
+ }
+ }
+ }
+ gpr_free(env);
+ }
+ if (overrideEnabled_ != -1) {
+ supportEnabled_ = (overrideEnabled_ == 1);
+ }
+ if (supportEnabled_) {
+ execCtxState_ = grpc_core::New<internal::ExecCtxState>();
+ threadState_ = grpc_core::New<internal::ThreadState>();
+ }
+}
+
+void Fork::GlobalShutdown() {
+ if (supportEnabled_) {
+ grpc_core::Delete(execCtxState_);
+ grpc_core::Delete(threadState_);
+ }
+}
+
+bool Fork::Enabled() { return supportEnabled_; }
+
+// Testing Only
+void Fork::Enable(bool enable) { overrideEnabled_ = enable ? 1 : 0; }
+
+void Fork::IncExecCtxCount() {
+ if (supportEnabled_) {
+ execCtxState_->IncExecCtxCount();
+ }
+}
+
+void Fork::DecExecCtxCount() {
+ if (supportEnabled_) {
+ execCtxState_->DecExecCtxCount();
+ }
+}
+
+bool Fork::BlockExecCtx() {
+ if (supportEnabled_) {
+ return execCtxState_->BlockExecCtx();
+ }
+ return false;
+}
+
+void Fork::AllowExecCtx() {
+ if (supportEnabled_) {
+ execCtxState_->AllowExecCtx();
+ }
+}
+
+void Fork::IncThreadCount() {
+ if (supportEnabled_) {
+ threadState_->IncThreadCount();
+ }
+}
+
+void Fork::DecThreadCount() {
+ if (supportEnabled_) {
+ threadState_->DecThreadCount();
+ }
+}
+void Fork::AwaitThreads() {
+ if (supportEnabled_) {
+ threadState_->AwaitThreads();
+ }
+}
+
+internal::ExecCtxState* Fork::execCtxState_ = nullptr;
+internal::ThreadState* Fork::threadState_ = nullptr;
+bool Fork::supportEnabled_ = false;
+int Fork::overrideEnabled_ = -1;
+
+} // namespace grpc_core
diff --git a/src/core/lib/gprpp/fork.h b/src/core/lib/gprpp/fork.h
new file mode 100644
index 0000000000..60ed74b1fb
--- /dev/null
+++ b/src/core/lib/gprpp/fork.h
@@ -0,0 +1,79 @@
+/*
+ *
+ * Copyright 2017 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.
+ *
+ */
+
+#ifndef GRPC_CORE_LIB_GPRPP_FORK_H
+#define GRPC_CORE_LIB_GPRPP_FORK_H
+
+/*
+ * NOTE: FORKING IS NOT GENERALLY SUPPORTED, THIS IS ONLY INTENDED TO WORK
+ * AROUND VERY SPECIFIC USE CASES.
+ */
+
+namespace grpc_core {
+
+namespace internal {
+class ExecCtxState;
+class ThreadState;
+} // namespace internal
+
+class Fork {
+ public:
+ static void GlobalInit();
+ static void GlobalShutdown();
+
+ // Returns true if fork suppport is enabled, false otherwise
+ static bool Enabled();
+
+ // Increment the count of active ExecCtxs.
+ // Will block until a pending fork is complete if one is in progress.
+ static void IncExecCtxCount();
+
+ // Decrement the count of active ExecCtxs
+ static void DecExecCtxCount();
+
+ // Check if there is a single active ExecCtx
+ // (the one used to invoke this function). If there are more,
+ // return false. Otherwise, return true and block creation of
+ // more ExecCtx s until AlloWExecCtx() is called
+ //
+ static bool BlockExecCtx();
+ static void AllowExecCtx();
+
+ // Increment the count of active threads.
+ static void IncThreadCount();
+
+ // Decrement the count of active threads.
+ static void DecThreadCount();
+
+ // Await all core threads to be joined.
+ static void AwaitThreads();
+
+ // Test only: overrides environment variables/compile flags
+ // Must be called before grpc_init()
+ static void Enable(bool enable);
+
+ private:
+ static internal::ExecCtxState* execCtxState_;
+ static internal::ThreadState* threadState_;
+ static bool supportEnabled_;
+ static int overrideEnabled_;
+};
+
+} // namespace grpc_core
+
+#endif /* GRPC_CORE_LIB_GPRPP_FORK_H */
diff --git a/src/core/lib/gprpp/thd.h b/src/core/lib/gprpp/thd.h
index 05c7ded45f..caf0652c1a 100644
--- a/src/core/lib/gprpp/thd.h
+++ b/src/core/lib/gprpp/thd.h
@@ -111,9 +111,6 @@ class Thread {
}
};
- static void Init();
- static bool AwaitAll(gpr_timespec deadline);
-
private:
Thread(const Thread&) = delete;
Thread& operator=(const Thread&) = delete;
diff --git a/src/core/lib/gprpp/thd_posix.cc b/src/core/lib/gprpp/thd_posix.cc
index 2f6c2edcae..533c07e7d8 100644
--- a/src/core/lib/gprpp/thd_posix.cc
+++ b/src/core/lib/gprpp/thd_posix.cc
@@ -32,17 +32,12 @@
#include <stdlib.h>
#include <string.h>
-#include "src/core/lib/gpr/fork.h"
#include "src/core/lib/gpr/useful.h"
+#include "src/core/lib/gprpp/fork.h"
#include "src/core/lib/gprpp/memory.h"
namespace grpc_core {
namespace {
-gpr_mu g_mu;
-gpr_cv g_cv;
-int g_thread_count;
-int g_awaiting_threads;
-
class ThreadInternalsPosix;
struct thd_arg {
ThreadInternalsPosix* thread;
@@ -68,7 +63,7 @@ class ThreadInternalsPosix
info->body = thd_body;
info->arg = arg;
info->name = thd_name;
- inc_thd_count();
+ grpc_core::Fork::IncThreadCount();
GPR_ASSERT(pthread_attr_init(&attr) == 0);
GPR_ASSERT(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE) ==
@@ -103,7 +98,7 @@ class ThreadInternalsPosix
gpr_mu_unlock(&arg.thread->mu_);
(*arg.body)(arg.arg);
- dec_thd_count();
+ grpc_core::Fork::DecThreadCount();
return nullptr;
},
info) == 0);
@@ -113,7 +108,7 @@ class ThreadInternalsPosix
if (!success) {
/* don't use gpr_free, as this was allocated using malloc (see above) */
free(info);
- dec_thd_count();
+ grpc_core::Fork::DecThreadCount();
}
};
@@ -132,29 +127,6 @@ class ThreadInternalsPosix
void Join() override { pthread_join(pthread_id_, nullptr); }
private:
- /*****************************************
- * Only used when fork support is enabled
- */
-
- static void inc_thd_count() {
- if (grpc_fork_support_enabled()) {
- gpr_mu_lock(&g_mu);
- g_thread_count++;
- gpr_mu_unlock(&g_mu);
- }
- }
-
- static void dec_thd_count() {
- if (grpc_fork_support_enabled()) {
- gpr_mu_lock(&g_mu);
- g_thread_count--;
- if (g_awaiting_threads && g_thread_count == 0) {
- gpr_cv_signal(&g_cv);
- }
- gpr_mu_unlock(&g_mu);
- }
- }
-
gpr_mu mu_;
gpr_cv ready_;
bool started_;
@@ -180,27 +152,6 @@ Thread::Thread(const char* thd_name, void (*thd_body)(void* arg), void* arg,
*success = outcome;
}
}
-
-void Thread::Init() {
- gpr_mu_init(&g_mu);
- gpr_cv_init(&g_cv);
- g_thread_count = 0;
- g_awaiting_threads = 0;
-}
-
-bool Thread::AwaitAll(gpr_timespec deadline) {
- gpr_mu_lock(&g_mu);
- g_awaiting_threads = 1;
- int res = 0;
- while ((g_thread_count > 0) &&
- (gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), deadline) < 0)) {
- res = gpr_cv_wait(&g_cv, &g_mu, deadline);
- }
- g_awaiting_threads = 0;
- gpr_mu_unlock(&g_mu);
- return res == 0;
-}
-
} // namespace grpc_core
// The following is in the external namespace as it is exposed as C89 API
diff --git a/src/core/lib/gprpp/thd_windows.cc b/src/core/lib/gprpp/thd_windows.cc
index 59ea02f3d2..71584fd358 100644
--- a/src/core/lib/gprpp/thd_windows.cc
+++ b/src/core/lib/gprpp/thd_windows.cc
@@ -131,13 +131,6 @@ class ThreadInternalsWindows
namespace grpc_core {
-void Thread::Init() {}
-
-bool Thread::AwaitAll(gpr_timespec deadline) {
- // TODO: Consider adding this if needed
- return false;
-}
-
Thread::Thread(const char* thd_name, void (*thd_body)(void* arg), void* arg,
bool* success) {
bool outcome = false;
diff --git a/src/core/lib/iomgr/exec_ctx.h b/src/core/lib/iomgr/exec_ctx.h
index 72d0ae58c1..d402181bc6 100644
--- a/src/core/lib/iomgr/exec_ctx.h
+++ b/src/core/lib/iomgr/exec_ctx.h
@@ -26,6 +26,7 @@
#include <grpc/support/log.h>
#include "src/core/lib/gpr/tls.h"
+#include "src/core/lib/gprpp/fork.h"
#include "src/core/lib/iomgr/closure.h"
typedef gpr_atm grpc_millis;
@@ -85,16 +86,23 @@ class ExecCtx {
public:
/** Default Constructor */
- ExecCtx() : flags_(GRPC_EXEC_CTX_FLAG_IS_FINISHED) { Set(this); }
+ ExecCtx() : flags_(GRPC_EXEC_CTX_FLAG_IS_FINISHED) {
+ grpc_core::Fork::IncExecCtxCount();
+ Set(this);
+ }
/** Parameterised Constructor */
- ExecCtx(uintptr_t fl) : flags_(fl) { Set(this); }
+ ExecCtx(uintptr_t fl) : flags_(fl) {
+ grpc_core::Fork::IncExecCtxCount();
+ Set(this);
+ }
/** Destructor */
virtual ~ExecCtx() {
flags_ |= GRPC_EXEC_CTX_FLAG_IS_FINISHED;
Flush();
Set(last_exec_ctx_);
+ grpc_core::Fork::DecExecCtxCount();
}
/** Disallow copy and assignment operators */
diff --git a/src/core/lib/iomgr/fork_posix.cc b/src/core/lib/iomgr/fork_posix.cc
index 6c506eb5c9..b37384b8db 100644
--- a/src/core/lib/iomgr/fork_posix.cc
+++ b/src/core/lib/iomgr/fork_posix.cc
@@ -28,7 +28,7 @@
#include <grpc/support/log.h>
#include "src/core/lib/gpr/env.h"
-#include "src/core/lib/gpr/fork.h"
+#include "src/core/lib/gprpp/fork.h"
#include "src/core/lib/gprpp/thd.h"
#include "src/core/lib/iomgr/ev_posix.h"
#include "src/core/lib/iomgr/executor.h"
@@ -41,46 +41,59 @@
* AROUND VERY SPECIFIC USE CASES.
*/
+namespace {
+bool skipped_handler = true;
+bool registered_handlers = false;
+} // namespace
+
void grpc_prefork() {
- if (!grpc_fork_support_enabled()) {
+ grpc_core::ExecCtx exec_ctx;
+ skipped_handler = true;
+ if (!grpc_is_initialized()) {
+ return;
+ }
+ if (!grpc_core::Fork::Enabled()) {
gpr_log(GPR_ERROR,
"Fork support not enabled; try running with the "
"environment variable GRPC_ENABLE_FORK_SUPPORT=1");
return;
}
- if (grpc_is_initialized()) {
- grpc_core::ExecCtx exec_ctx;
- grpc_timer_manager_set_threading(false);
- grpc_executor_set_threading(false);
- grpc_core::ExecCtx::Get()->Flush();
- if (!grpc_core::Thread::AwaitAll(
- gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
- gpr_time_from_seconds(3, GPR_TIMESPAN)))) {
- gpr_log(GPR_ERROR, "gRPC thread still active! Cannot fork!");
- }
+ if (!grpc_core::Fork::BlockExecCtx()) {
+ gpr_log(GPR_INFO,
+ "Other threads are currently calling into gRPC, skipping fork() "
+ "handlers");
+ return;
}
+ grpc_timer_manager_set_threading(false);
+ grpc_executor_set_threading(false);
+ grpc_core::ExecCtx::Get()->Flush();
+ grpc_core::Fork::AwaitThreads();
+ skipped_handler = false;
}
void grpc_postfork_parent() {
- if (grpc_is_initialized()) {
- grpc_timer_manager_set_threading(true);
+ if (!skipped_handler) {
+ grpc_core::Fork::AllowExecCtx();
grpc_core::ExecCtx exec_ctx;
+ grpc_timer_manager_set_threading(true);
grpc_executor_set_threading(true);
}
}
void grpc_postfork_child() {
- if (grpc_is_initialized()) {
- grpc_timer_manager_set_threading(true);
+ if (!skipped_handler) {
+ grpc_core::Fork::AllowExecCtx();
grpc_core::ExecCtx exec_ctx;
+ grpc_timer_manager_set_threading(true);
grpc_executor_set_threading(true);
}
}
void grpc_fork_handlers_auto_register() {
- if (grpc_fork_support_enabled()) {
+ if (grpc_core::Fork::Enabled() & !registered_handlers) {
#ifdef GRPC_POSIX_FORK_ALLOW_PTHREAD_ATFORK
pthread_atfork(grpc_prefork, grpc_postfork_parent, grpc_postfork_child);
+ registered_handlers = true;
#endif // GRPC_POSIX_FORK_ALLOW_PTHREAD_ATFORK
}
}
diff --git a/src/core/lib/surface/init.cc b/src/core/lib/surface/init.cc
index bd436d6857..a14f77e346 100644
--- a/src/core/lib/surface/init.cc
+++ b/src/core/lib/surface/init.cc
@@ -32,8 +32,7 @@
#include "src/core/lib/channel/handshaker_registry.h"
#include "src/core/lib/debug/stats.h"
#include "src/core/lib/debug/trace.h"
-#include "src/core/lib/gpr/fork.h"
-#include "src/core/lib/gprpp/thd.h"
+#include "src/core/lib/gprpp/fork.h"
#include "src/core/lib/http/parser.h"
#include "src/core/lib/iomgr/call_combiner.h"
#include "src/core/lib/iomgr/combiner.h"
@@ -65,12 +64,10 @@ static int g_initializations;
static void do_basic_init(void) {
gpr_log_verbosity_init();
- grpc_fork_support_init();
gpr_mu_init(&g_init_mu);
grpc_register_built_in_plugins();
grpc_cq_global_init();
g_initializations = 0;
- grpc_fork_handlers_auto_register();
}
static bool append_filter(grpc_channel_stack_builder* builder, void* arg) {
@@ -123,8 +120,9 @@ void grpc_init(void) {
gpr_mu_lock(&g_init_mu);
if (++g_initializations == 1) {
+ grpc_core::Fork::GlobalInit();
+ grpc_fork_handlers_auto_register();
gpr_time_init();
- grpc_core::Thread::Init();
grpc_stats_init();
grpc_slice_intern_init();
grpc_mdctx_global_init();
@@ -180,6 +178,7 @@ void grpc_shutdown(void) {
grpc_slice_intern_shutdown();
grpc_channel_trace_registry_shutdown();
grpc_stats_shutdown();
+ grpc_core::Fork::GlobalShutdown();
}
grpc_core::ExecCtx::GlobalShutdown();
}
diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py
index 699d504c12..bf6c2534a8 100644
--- a/src/python/grpcio/grpc_core_dependencies.py
+++ b/src/python/grpcio/grpc_core_dependencies.py
@@ -28,7 +28,6 @@ CORE_SOURCE_FILES = [
'src/core/lib/gpr/env_linux.cc',
'src/core/lib/gpr/env_posix.cc',
'src/core/lib/gpr/env_windows.cc',
- 'src/core/lib/gpr/fork.cc',
'src/core/lib/gpr/host_port.cc',
'src/core/lib/gpr/log.cc',
'src/core/lib/gpr/log_android.cc',
@@ -53,6 +52,7 @@ CORE_SOURCE_FILES = [
'src/core/lib/gpr/tmpfile_posix.cc',
'src/core/lib/gpr/tmpfile_windows.cc',
'src/core/lib/gpr/wrap_memcpy.cc',
+ 'src/core/lib/gprpp/fork.cc',
'src/core/lib/gprpp/thd_posix.cc',
'src/core/lib/gprpp/thd_windows.cc',
'src/core/lib/profiling/basic_timers.cc',
diff --git a/test/core/gprpp/BUILD b/test/core/gprpp/BUILD
index a8a5739552..e7232d9df8 100644
--- a/test/core/gprpp/BUILD
+++ b/test/core/gprpp/BUILD
@@ -19,6 +19,16 @@ licenses(["notice"]) # Apache v2
grpc_package(name = "test/core/gprpp")
grpc_cc_test(
+ name = "fork_test",
+ srcs = ["fork_test.cc"],
+ language = "C++",
+ deps = [
+ "//:gpr",
+ "//test/core/util:gpr_test_util",
+ ],
+)
+
+grpc_cc_test(
name = "manual_constructor_test",
srcs = ["manual_constructor_test.cc"],
language = "C++",
diff --git a/test/core/gprpp/fork_test.cc b/test/core/gprpp/fork_test.cc
new file mode 100644
index 0000000000..c4a8a4e5f5
--- /dev/null
+++ b/test/core/gprpp/fork_test.cc
@@ -0,0 +1,136 @@
+/*
+ *
+ * Copyright 2017 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 "src/core/lib/gprpp/fork.h"
+
+#include "src/core/lib/gprpp/thd.h"
+#include "test/core/util/test_config.h"
+
+static void test_init() {
+ GPR_ASSERT(!grpc_core::Fork::Enabled());
+
+ // Default fork support (disabled)
+ grpc_core::Fork::GlobalInit();
+ GPR_ASSERT(!grpc_core::Fork::Enabled());
+ grpc_core::Fork::GlobalShutdown();
+
+ // Explicitly disabled fork support
+ grpc_core::Fork::Enable(false);
+ grpc_core::Fork::GlobalInit();
+ GPR_ASSERT(!grpc_core::Fork::Enabled());
+ grpc_core::Fork::GlobalShutdown();
+
+ // Explicitly enabled fork support
+ grpc_core::Fork::Enable(true);
+ grpc_core::Fork::GlobalInit();
+ GPR_ASSERT(grpc_core::Fork::Enabled());
+ grpc_core::Fork::GlobalShutdown();
+}
+
+#define THREAD_DELAY_MS 3000
+#define THREAD_DELAY_EPSILON 500
+#define CONCURRENT_TEST_THREADS 100
+
+static void sleeping_thd(void* arg) {
+ int64_t sleep_ms = (int64_t)arg;
+ gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
+ gpr_time_from_millis(sleep_ms, GPR_TIMESPAN)));
+}
+
+static void test_thd_count() {
+ // Test no active threads
+ grpc_core::Fork::Enable(true);
+ grpc_core::Fork::GlobalInit();
+ grpc_core::Fork::AwaitThreads();
+ grpc_core::Fork::GlobalShutdown();
+
+ grpc_core::Fork::Enable(true);
+ grpc_core::Fork::GlobalInit();
+ grpc_core::Thread thds[CONCURRENT_TEST_THREADS];
+ gpr_timespec est_end_time =
+ gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
+ gpr_time_from_millis(THREAD_DELAY_MS, GPR_TIMESPAN));
+ gpr_timespec tolerance =
+ gpr_time_from_millis(THREAD_DELAY_EPSILON, GPR_TIMESPAN);
+ for (int i = 0; i < CONCURRENT_TEST_THREADS; i++) {
+ intptr_t sleep_time_ms =
+ (i * THREAD_DELAY_MS) / (CONCURRENT_TEST_THREADS - 1);
+ thds[i] =
+ grpc_core::Thread("grpc_fork_test", sleeping_thd, (void*)sleep_time_ms);
+ thds[i].Start();
+ }
+ grpc_core::Fork::AwaitThreads();
+ gpr_timespec end_time = gpr_now(GPR_CLOCK_REALTIME);
+ for (auto& thd : thds) {
+ thd.Join();
+ }
+ GPR_ASSERT(gpr_time_similar(end_time, est_end_time, tolerance));
+ grpc_core::Fork::GlobalShutdown();
+}
+
+static void exec_ctx_thread(void* arg) {
+ bool* exec_ctx_created = (bool*)arg;
+ grpc_core::Fork::IncExecCtxCount();
+ *exec_ctx_created = true;
+}
+
+static void test_exec_count() {
+ grpc_core::Fork::IncExecCtxCount();
+ grpc_core::Fork::Enable(true);
+ grpc_core::Fork::GlobalInit();
+
+ grpc_core::Fork::IncExecCtxCount();
+ GPR_ASSERT(grpc_core::Fork::BlockExecCtx());
+ grpc_core::Fork::DecExecCtxCount();
+ grpc_core::Fork::AllowExecCtx();
+
+ grpc_core::Fork::IncExecCtxCount();
+ grpc_core::Fork::IncExecCtxCount();
+ GPR_ASSERT(!grpc_core::Fork::BlockExecCtx());
+ grpc_core::Fork::DecExecCtxCount();
+ grpc_core::Fork::DecExecCtxCount();
+
+ grpc_core::Fork::IncExecCtxCount();
+ GPR_ASSERT(grpc_core::Fork::BlockExecCtx());
+ grpc_core::Fork::DecExecCtxCount();
+ grpc_core::Fork::AllowExecCtx();
+
+ // Test that block_exec_ctx() blocks grpc_core::Fork::IncExecCtxCount
+ bool exec_ctx_created = false;
+ grpc_core::Thread thd =
+ grpc_core::Thread("grpc_fork_test", exec_ctx_thread, &exec_ctx_created);
+ grpc_core::Fork::IncExecCtxCount();
+ GPR_ASSERT(grpc_core::Fork::BlockExecCtx());
+ grpc_core::Fork::DecExecCtxCount();
+ thd.Start();
+ gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
+ gpr_time_from_seconds(1, GPR_TIMESPAN)));
+ GPR_ASSERT(!exec_ctx_created);
+ grpc_core::Fork::AllowExecCtx();
+ thd.Join(); // This ensure that the call got un-blocked
+ grpc_core::Fork::GlobalShutdown();
+}
+
+int main(int argc, char* argv[]) {
+ grpc_test_init(argc, argv);
+ test_init();
+ test_thd_count();
+ test_exec_count();
+
+ return 0;
+}
diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal
index 7c6b75d8ed..37a936b7cd 100644
--- a/tools/doxygen/Doxyfile.c++.internal
+++ b/tools/doxygen/Doxyfile.c++.internal
@@ -1031,7 +1031,6 @@ src/core/lib/debug/stats_data.h \
src/core/lib/debug/trace.h \
src/core/lib/gpr/arena.h \
src/core/lib/gpr/env.h \
-src/core/lib/gpr/fork.h \
src/core/lib/gpr/host_port.h \
src/core/lib/gpr/mpscq.h \
src/core/lib/gpr/murmur_hash.h \
@@ -1050,6 +1049,7 @@ src/core/lib/gprpp/atomic.h \
src/core/lib/gprpp/atomic_with_atm.h \
src/core/lib/gprpp/atomic_with_std.h \
src/core/lib/gprpp/debug_location.h \
+src/core/lib/gprpp/fork.h \
src/core/lib/gprpp/inlined_vector.h \
src/core/lib/gprpp/manual_constructor.h \
src/core/lib/gprpp/memory.h \
diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal
index 2d1541279e..6ae1c490a6 100644
--- a/tools/doxygen/Doxyfile.core.internal
+++ b/tools/doxygen/Doxyfile.core.internal
@@ -1083,8 +1083,6 @@ src/core/lib/gpr/env.h \
src/core/lib/gpr/env_linux.cc \
src/core/lib/gpr/env_posix.cc \
src/core/lib/gpr/env_windows.cc \
-src/core/lib/gpr/fork.cc \
-src/core/lib/gpr/fork.h \
src/core/lib/gpr/host_port.cc \
src/core/lib/gpr/host_port.h \
src/core/lib/gpr/log.cc \
@@ -1128,6 +1126,8 @@ src/core/lib/gprpp/atomic.h \
src/core/lib/gprpp/atomic_with_atm.h \
src/core/lib/gprpp/atomic_with_std.h \
src/core/lib/gprpp/debug_location.h \
+src/core/lib/gprpp/fork.cc \
+src/core/lib/gprpp/fork.h \
src/core/lib/gprpp/inlined_vector.h \
src/core/lib/gprpp/manual_constructor.h \
src/core/lib/gprpp/memory.h \
diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json
index 4f0fc1d30d..d7dc75b80e 100644
--- a/tools/run_tests/generated/sources_and_headers.json
+++ b/tools/run_tests/generated/sources_and_headers.json
@@ -605,6 +605,21 @@
{
"deps": [
"gpr",
+ "gpr_test_util"
+ ],
+ "headers": [],
+ "is_filegroup": false,
+ "language": "c",
+ "name": "fork_test",
+ "src": [
+ "test/core/gprpp/fork_test.cc"
+ ],
+ "third_party": false,
+ "type": "target"
+ },
+ {
+ "deps": [
+ "gpr",
"gpr_test_util",
"grpc",
"grpc_test_util"
@@ -9012,7 +9027,6 @@
"src/core/lib/gpr/env_linux.cc",
"src/core/lib/gpr/env_posix.cc",
"src/core/lib/gpr/env_windows.cc",
- "src/core/lib/gpr/fork.cc",
"src/core/lib/gpr/host_port.cc",
"src/core/lib/gpr/log.cc",
"src/core/lib/gpr/log_android.cc",
@@ -9037,6 +9051,7 @@
"src/core/lib/gpr/tmpfile_posix.cc",
"src/core/lib/gpr/tmpfile_windows.cc",
"src/core/lib/gpr/wrap_memcpy.cc",
+ "src/core/lib/gprpp/fork.cc",
"src/core/lib/gprpp/thd_posix.cc",
"src/core/lib/gprpp/thd_windows.cc",
"src/core/lib/profiling/basic_timers.cc",
@@ -9069,7 +9084,6 @@
"include/grpc/support/time.h",
"src/core/lib/gpr/arena.h",
"src/core/lib/gpr/env.h",
- "src/core/lib/gpr/fork.h",
"src/core/lib/gpr/host_port.h",
"src/core/lib/gpr/mpscq.h",
"src/core/lib/gpr/murmur_hash.h",
@@ -9087,6 +9101,7 @@
"src/core/lib/gprpp/atomic.h",
"src/core/lib/gprpp/atomic_with_atm.h",
"src/core/lib/gprpp/atomic_with_std.h",
+ "src/core/lib/gprpp/fork.h",
"src/core/lib/gprpp/manual_constructor.h",
"src/core/lib/gprpp/memory.h",
"src/core/lib/gprpp/thd.h",
@@ -9115,7 +9130,6 @@
"include/grpc/support/time.h",
"src/core/lib/gpr/arena.h",
"src/core/lib/gpr/env.h",
- "src/core/lib/gpr/fork.h",
"src/core/lib/gpr/host_port.h",
"src/core/lib/gpr/mpscq.h",
"src/core/lib/gpr/murmur_hash.h",
@@ -9133,6 +9147,7 @@
"src/core/lib/gprpp/atomic.h",
"src/core/lib/gprpp/atomic_with_atm.h",
"src/core/lib/gprpp/atomic_with_std.h",
+ "src/core/lib/gprpp/fork.h",
"src/core/lib/gprpp/manual_constructor.h",
"src/core/lib/gprpp/memory.h",
"src/core/lib/gprpp/thd.h",
diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json
index 701f44fb92..461323380d 100644
--- a/tools/run_tests/generated/tests.json
+++ b/tools/run_tests/generated/tests.json
@@ -724,6 +724,26 @@
"benchmark": false,
"ci_platforms": [
"linux",
+ "mac"
+ ],
+ "cpu_cost": 1.0,
+ "exclude_configs": [],
+ "exclude_iomgrs": [],
+ "flaky": false,
+ "gtest": false,
+ "language": "c",
+ "name": "fork_test",
+ "platforms": [
+ "linux",
+ "mac"
+ ],
+ "uses_polling": false
+ },
+ {
+ "args": [],
+ "benchmark": false,
+ "ci_platforms": [
+ "linux",
"mac",
"posix"
],