proxygen
SubprocessTestParentDeathHelper.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2013-present Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 // This is a helper for the parentDeathSignal test in SubprocessTest.cpp.
18 //
19 // Basically, we create two processes, a parent and a child, and set the
20 // child to receive SIGUSR1 when the parent exits. We set the child to
21 // create a file when that happens. The child then kills the parent; the test
22 // will verify that the file actually gets created, which means that everything
23 // worked as intended.
24 
25 #include <fcntl.h>
26 #include <signal.h>
27 #include <sys/types.h>
28 
29 #include <glog/logging.h>
30 
31 #include <folly/Conv.h>
32 #include <folly/Subprocess.h>
35 
36 using folly::Subprocess;
37 
38 DEFINE_bool(child, false, "");
39 
40 namespace {
41 constexpr int kSignal = SIGUSR1;
42 } // namespace
43 
44 void runChild(const char* file) {
45  // Block SIGUSR1 so it's queued
46  sigset_t sigs;
47  CHECK_ERR(sigemptyset(&sigs));
48  CHECK_ERR(sigaddset(&sigs, kSignal));
49  CHECK_ERR(sigprocmask(SIG_BLOCK, &sigs, nullptr));
50 
51  // Kill the parent, wait for our signal.
52  CHECK_ERR(kill(getppid(), SIGKILL));
53 
54  int sig = 0;
55  CHECK_ERR(sigwait(&sigs, &sig));
56  CHECK_EQ(sig, kSignal);
57 
58  // Signal completion by creating the file
59  CHECK_ERR(creat(file, 0600));
60 }
61 
62 [[noreturn]] void runParent(const char* file) {
63  std::vector<std::string> args{"/proc/self/exe", "--child", file};
64  Subprocess proc(args, Subprocess::Options().parentDeathSignal(kSignal));
65  CHECK(proc.poll().running());
66 
67  // The child will kill us.
68  for (;;) {
69  pause();
70  }
71 }
72 
73 int main(int argc, char* argv[]) {
74  gflags::ParseCommandLineFlags(&argc, &argv, true);
75  CHECK_EQ(argc, 2);
76  if (FLAGS_child) {
77  runChild(argv[1]);
78  } else {
79  runParent(argv[1]);
80  }
81  return 0;
82 }
void runParent(const char *file)
void runChild(const char *file)
int main(int argc, char *argv[])
bool running() const
Definition: Subprocess.h:177
char ** argv
constexpr detail::Sig< Sig > const sig
Definition: Poly.h:1165
DEFINE_bool(child, false,"")
folly::Function< void()> child
Definition: AtFork.cpp:35
ProcessReturnCode poll(struct rusage *ru=nullptr)
Definition: Subprocess.cpp:618