Implement graceful SIGTERM handling in the process-wrapper.

This is intended to be used with the new dynamic spawn scheduler (via the
--process_wrapper_extra_flags flag), which triggers lots more local process
cancellations, in an attempt to workaround an odd OSXFUSE bug for which we
have no diagnostic nor fix yet.

Part of #7818.

RELNOTES: None.
PiperOrigin-RevId: 314953746
diff --git a/src/main/tools/process-wrapper-options.cc b/src/main/tools/process-wrapper-options.cc
index 837fd26..0c0e97e 100644
--- a/src/main/tools/process-wrapper-options.cc
+++ b/src/main/tools/process-wrapper-options.cc
@@ -41,6 +41,8 @@
   fprintf(
       stderr,
       "\nPossible arguments:\n"
+      "  -g/--graceful_sigterm  propagate SIGTERM to the subprocess and delay "
+      "the corresponding SIGKILL until --kill_delay has passed\n"
       "  -t/--timeout <timeout>  timeout after which the child process will be "
       "terminated with SIGTERM\n"
       "  -k/--kill_delay <timeout>  in case timeout occurs, how long to wait "
@@ -58,6 +60,7 @@
 // global `opt` struct.
 static void ParseCommandLine(const std::vector<char *> &args) {
   static struct option long_options[] = {
+      {"graceful_sigterm", no_argument, 0, 'g'},
       {"timeout", required_argument, 0, 't'},
       {"kill_delay", required_argument, 0, 'k'},
       {"stdout", required_argument, 0, 'o'},
@@ -70,9 +73,12 @@
   extern int optind, optopt;
   int c;
 
-  while ((c = getopt_long(args.size(), args.data(), "+:t:k:o:e:s:dW",
+  while ((c = getopt_long(args.size(), args.data(), "+:gt:k:o:e:s:dW",
                           long_options, nullptr)) != -1) {
     switch (c) {
+      case 'g':
+        opt.graceful_sigterm = true;
+        break;
       case 't':
         if (sscanf(optarg, "%lf", &opt.timeout_secs) != 1) {
           Usage(args.front(), "Invalid timeout (-t) value: %s", optarg);