Admin/bash_process/bash_process.c
author wenzelm
Thu, 22 Apr 2021 22:07:05 +0200
changeset 73599 981df2e1f646
parent 62575 590df5f4e531
permissions -rw-r--r--
clarified command-line;
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
47764
d141f1193789 more direct bash process group invocation on Cygwin, bypassing extra sh.exe and perl.exe which tend to crash;
wenzelm
parents:
diff changeset
     1
/*  Author:     Makarius
d141f1193789 more direct bash process group invocation on Cygwin, bypassing extra sh.exe and perl.exe which tend to crash;
wenzelm
parents:
diff changeset
     2
62292
486236dcd4d7 more flexible command-line;
wenzelm
parents: 50292
diff changeset
     3
Bash process with separate process group id.
47764
d141f1193789 more direct bash process group invocation on Cygwin, bypassing extra sh.exe and perl.exe which tend to crash;
wenzelm
parents:
diff changeset
     4
*/
d141f1193789 more direct bash process group invocation on Cygwin, bypassing extra sh.exe and perl.exe which tend to crash;
wenzelm
parents:
diff changeset
     5
62575
590df5f4e531 ignore SIGINT in waiting wrapper process;
wenzelm
parents: 62568
diff changeset
     6
#include <signal.h>
62567
cb4e6ca06505 support for timing of the managed process;
wenzelm
parents: 62300
diff changeset
     7
#include <stdio.h>
47764
d141f1193789 more direct bash process group invocation on Cygwin, bypassing extra sh.exe and perl.exe which tend to crash;
wenzelm
parents:
diff changeset
     8
#include <stdlib.h>
62292
486236dcd4d7 more flexible command-line;
wenzelm
parents: 50292
diff changeset
     9
#include <string.h>
62567
cb4e6ca06505 support for timing of the managed process;
wenzelm
parents: 62300
diff changeset
    10
#include <sys/resource.h>
cb4e6ca06505 support for timing of the managed process;
wenzelm
parents: 62300
diff changeset
    11
#include <sys/time.h>
47764
d141f1193789 more direct bash process group invocation on Cygwin, bypassing extra sh.exe and perl.exe which tend to crash;
wenzelm
parents:
diff changeset
    12
#include <sys/types.h>
62300
f41884b9c4f1 actually wait for forked process and return its status -- this is not meant to be a daemon;
wenzelm
parents: 62293
diff changeset
    13
#include <sys/wait.h>
62567
cb4e6ca06505 support for timing of the managed process;
wenzelm
parents: 62300
diff changeset
    14
#include <time.h>
47764
d141f1193789 more direct bash process group invocation on Cygwin, bypassing extra sh.exe and perl.exe which tend to crash;
wenzelm
parents:
diff changeset
    15
#include <unistd.h>
d141f1193789 more direct bash process group invocation on Cygwin, bypassing extra sh.exe and perl.exe which tend to crash;
wenzelm
parents:
diff changeset
    16
d141f1193789 more direct bash process group invocation on Cygwin, bypassing extra sh.exe and perl.exe which tend to crash;
wenzelm
parents:
diff changeset
    17
static void fail(const char *msg)
d141f1193789 more direct bash process group invocation on Cygwin, bypassing extra sh.exe and perl.exe which tend to crash;
wenzelm
parents:
diff changeset
    18
{
47798
03ab3bd78282 print errors on stderr;
wenzelm
parents: 47797
diff changeset
    19
  fprintf(stderr, "%s\n", msg);
62292
486236dcd4d7 more flexible command-line;
wenzelm
parents: 50292
diff changeset
    20
  fflush(stderr);
47764
d141f1193789 more direct bash process group invocation on Cygwin, bypassing extra sh.exe and perl.exe which tend to crash;
wenzelm
parents:
diff changeset
    21
  exit(2);
d141f1193789 more direct bash process group invocation on Cygwin, bypassing extra sh.exe and perl.exe which tend to crash;
wenzelm
parents:
diff changeset
    22
}
d141f1193789 more direct bash process group invocation on Cygwin, bypassing extra sh.exe and perl.exe which tend to crash;
wenzelm
parents:
diff changeset
    23
62568
3541bc1e97d2 elapsed time in milliseconds (cf. Time.now in Poly/ML);
wenzelm
parents: 62567
diff changeset
    24
static time_t now()
3541bc1e97d2 elapsed time in milliseconds (cf. Time.now in Poly/ML);
wenzelm
parents: 62567
diff changeset
    25
{
3541bc1e97d2 elapsed time in milliseconds (cf. Time.now in Poly/ML);
wenzelm
parents: 62567
diff changeset
    26
  struct timeval tv;
3541bc1e97d2 elapsed time in milliseconds (cf. Time.now in Poly/ML);
wenzelm
parents: 62567
diff changeset
    27
  if (gettimeofday(&tv, NULL) == 0) {
3541bc1e97d2 elapsed time in milliseconds (cf. Time.now in Poly/ML);
wenzelm
parents: 62567
diff changeset
    28
    return tv.tv_sec * 1000 + tv.tv_usec / 1000;
3541bc1e97d2 elapsed time in milliseconds (cf. Time.now in Poly/ML);
wenzelm
parents: 62567
diff changeset
    29
  }
3541bc1e97d2 elapsed time in milliseconds (cf. Time.now in Poly/ML);
wenzelm
parents: 62567
diff changeset
    30
  else {
3541bc1e97d2 elapsed time in milliseconds (cf. Time.now in Poly/ML);
wenzelm
parents: 62567
diff changeset
    31
    return time(NULL) * 1000;
3541bc1e97d2 elapsed time in milliseconds (cf. Time.now in Poly/ML);
wenzelm
parents: 62567
diff changeset
    32
  }
3541bc1e97d2 elapsed time in milliseconds (cf. Time.now in Poly/ML);
wenzelm
parents: 62567
diff changeset
    33
}
3541bc1e97d2 elapsed time in milliseconds (cf. Time.now in Poly/ML);
wenzelm
parents: 62567
diff changeset
    34
47764
d141f1193789 more direct bash process group invocation on Cygwin, bypassing extra sh.exe and perl.exe which tend to crash;
wenzelm
parents:
diff changeset
    35
d141f1193789 more direct bash process group invocation on Cygwin, bypassing extra sh.exe and perl.exe which tend to crash;
wenzelm
parents:
diff changeset
    36
int main(int argc, char *argv[])
d141f1193789 more direct bash process group invocation on Cygwin, bypassing extra sh.exe and perl.exe which tend to crash;
wenzelm
parents:
diff changeset
    37
{
d141f1193789 more direct bash process group invocation on Cygwin, bypassing extra sh.exe and perl.exe which tend to crash;
wenzelm
parents:
diff changeset
    38
  /* args */
d141f1193789 more direct bash process group invocation on Cygwin, bypassing extra sh.exe and perl.exe which tend to crash;
wenzelm
parents:
diff changeset
    39
73599
981df2e1f646 clarified command-line;
wenzelm
parents: 62575
diff changeset
    40
  if (argc < 2) {
981df2e1f646 clarified command-line;
wenzelm
parents: 62575
diff changeset
    41
    fprintf(stderr, "Bad arguments: missing TIMING_FILE\n");
62292
486236dcd4d7 more flexible command-line;
wenzelm
parents: 50292
diff changeset
    42
    fflush(stderr);
47764
d141f1193789 more direct bash process group invocation on Cygwin, bypassing extra sh.exe and perl.exe which tend to crash;
wenzelm
parents:
diff changeset
    43
    exit(1);
d141f1193789 more direct bash process group invocation on Cygwin, bypassing extra sh.exe and perl.exe which tend to crash;
wenzelm
parents:
diff changeset
    44
  }
73599
981df2e1f646 clarified command-line;
wenzelm
parents: 62575
diff changeset
    45
  char *timing_name = argv[1];
47764
d141f1193789 more direct bash process group invocation on Cygwin, bypassing extra sh.exe and perl.exe which tend to crash;
wenzelm
parents:
diff changeset
    46
d141f1193789 more direct bash process group invocation on Cygwin, bypassing extra sh.exe and perl.exe which tend to crash;
wenzelm
parents:
diff changeset
    47
62567
cb4e6ca06505 support for timing of the managed process;
wenzelm
parents: 62300
diff changeset
    48
  /* potential fork */
47764
d141f1193789 more direct bash process group invocation on Cygwin, bypassing extra sh.exe and perl.exe which tend to crash;
wenzelm
parents:
diff changeset
    49
62568
3541bc1e97d2 elapsed time in milliseconds (cf. Time.now in Poly/ML);
wenzelm
parents: 62567
diff changeset
    50
  time_t time_start = now();
62567
cb4e6ca06505 support for timing of the managed process;
wenzelm
parents: 62300
diff changeset
    51
cb4e6ca06505 support for timing of the managed process;
wenzelm
parents: 62300
diff changeset
    52
  if (strlen(timing_name) > 0 || setsid() == -1) {
50290
735bea8d89c9 more defensive retry via fork;
wenzelm
parents: 49551
diff changeset
    53
    pid_t pid = fork();
62300
f41884b9c4f1 actually wait for forked process and return its status -- this is not meant to be a daemon;
wenzelm
parents: 62293
diff changeset
    54
50290
735bea8d89c9 more defensive retry via fork;
wenzelm
parents: 49551
diff changeset
    55
    if (pid == -1) fail("Cannot set session id (failed to fork)");
62300
f41884b9c4f1 actually wait for forked process and return its status -- this is not meant to be a daemon;
wenzelm
parents: 62293
diff changeset
    56
    else if (pid != 0) {
62567
cb4e6ca06505 support for timing of the managed process;
wenzelm
parents: 62300
diff changeset
    57
      int status;
cb4e6ca06505 support for timing of the managed process;
wenzelm
parents: 62300
diff changeset
    58
62575
590df5f4e531 ignore SIGINT in waiting wrapper process;
wenzelm
parents: 62568
diff changeset
    59
      // ingore SIGINT
590df5f4e531 ignore SIGINT in waiting wrapper process;
wenzelm
parents: 62568
diff changeset
    60
      struct sigaction sa;
590df5f4e531 ignore SIGINT in waiting wrapper process;
wenzelm
parents: 62568
diff changeset
    61
      memset(&sa, 0, sizeof(sa));
590df5f4e531 ignore SIGINT in waiting wrapper process;
wenzelm
parents: 62568
diff changeset
    62
      sa.sa_handler = SIG_IGN;
590df5f4e531 ignore SIGINT in waiting wrapper process;
wenzelm
parents: 62568
diff changeset
    63
      sigaction(SIGINT, &sa, 0);
590df5f4e531 ignore SIGINT in waiting wrapper process;
wenzelm
parents: 62568
diff changeset
    64
62300
f41884b9c4f1 actually wait for forked process and return its status -- this is not meant to be a daemon;
wenzelm
parents: 62293
diff changeset
    65
      if (waitpid(pid, &status, 0) == -1) {
f41884b9c4f1 actually wait for forked process and return its status -- this is not meant to be a daemon;
wenzelm
parents: 62293
diff changeset
    66
        fail("Cannot join forked process");
f41884b9c4f1 actually wait for forked process and return its status -- this is not meant to be a daemon;
wenzelm
parents: 62293
diff changeset
    67
      }
f41884b9c4f1 actually wait for forked process and return its status -- this is not meant to be a daemon;
wenzelm
parents: 62293
diff changeset
    68
62567
cb4e6ca06505 support for timing of the managed process;
wenzelm
parents: 62300
diff changeset
    69
      /* report timing */
cb4e6ca06505 support for timing of the managed process;
wenzelm
parents: 62300
diff changeset
    70
cb4e6ca06505 support for timing of the managed process;
wenzelm
parents: 62300
diff changeset
    71
      if (strlen(timing_name) > 0) {
62568
3541bc1e97d2 elapsed time in milliseconds (cf. Time.now in Poly/ML);
wenzelm
parents: 62567
diff changeset
    72
        long long timing_elapsed = now() - time_start;
62567
cb4e6ca06505 support for timing of the managed process;
wenzelm
parents: 62300
diff changeset
    73
cb4e6ca06505 support for timing of the managed process;
wenzelm
parents: 62300
diff changeset
    74
        struct rusage ru;
cb4e6ca06505 support for timing of the managed process;
wenzelm
parents: 62300
diff changeset
    75
        getrusage(RUSAGE_CHILDREN, &ru);
cb4e6ca06505 support for timing of the managed process;
wenzelm
parents: 62300
diff changeset
    76
cb4e6ca06505 support for timing of the managed process;
wenzelm
parents: 62300
diff changeset
    77
        long long timing_cpu =
cb4e6ca06505 support for timing of the managed process;
wenzelm
parents: 62300
diff changeset
    78
          ru.ru_utime.tv_sec * 1000 + ru.ru_utime.tv_usec / 1000 +
cb4e6ca06505 support for timing of the managed process;
wenzelm
parents: 62300
diff changeset
    79
          ru.ru_stime.tv_sec * 1000 + ru.ru_stime.tv_usec / 1000;
cb4e6ca06505 support for timing of the managed process;
wenzelm
parents: 62300
diff changeset
    80
cb4e6ca06505 support for timing of the managed process;
wenzelm
parents: 62300
diff changeset
    81
        FILE *timing_file = fopen(timing_name, "w");
cb4e6ca06505 support for timing of the managed process;
wenzelm
parents: 62300
diff changeset
    82
        if (timing_file == NULL) fail("Cannot open timing file");
cb4e6ca06505 support for timing of the managed process;
wenzelm
parents: 62300
diff changeset
    83
        fprintf(timing_file, "%lld %lld", timing_elapsed, timing_cpu);
cb4e6ca06505 support for timing of the managed process;
wenzelm
parents: 62300
diff changeset
    84
        fclose(timing_file);
cb4e6ca06505 support for timing of the managed process;
wenzelm
parents: 62300
diff changeset
    85
      }
cb4e6ca06505 support for timing of the managed process;
wenzelm
parents: 62300
diff changeset
    86
62300
f41884b9c4f1 actually wait for forked process and return its status -- this is not meant to be a daemon;
wenzelm
parents: 62293
diff changeset
    87
      if (WIFEXITED(status)) {
f41884b9c4f1 actually wait for forked process and return its status -- this is not meant to be a daemon;
wenzelm
parents: 62293
diff changeset
    88
        exit(WEXITSTATUS(status));
f41884b9c4f1 actually wait for forked process and return its status -- this is not meant to be a daemon;
wenzelm
parents: 62293
diff changeset
    89
      }
f41884b9c4f1 actually wait for forked process and return its status -- this is not meant to be a daemon;
wenzelm
parents: 62293
diff changeset
    90
      else if (WIFSIGNALED(status)) {
f41884b9c4f1 actually wait for forked process and return its status -- this is not meant to be a daemon;
wenzelm
parents: 62293
diff changeset
    91
        exit(128 + WTERMSIG(status));
f41884b9c4f1 actually wait for forked process and return its status -- this is not meant to be a daemon;
wenzelm
parents: 62293
diff changeset
    92
      }
f41884b9c4f1 actually wait for forked process and return its status -- this is not meant to be a daemon;
wenzelm
parents: 62293
diff changeset
    93
      else {
f41884b9c4f1 actually wait for forked process and return its status -- this is not meant to be a daemon;
wenzelm
parents: 62293
diff changeset
    94
        fail("Unknown status of forked process");
f41884b9c4f1 actually wait for forked process and return its status -- this is not meant to be a daemon;
wenzelm
parents: 62293
diff changeset
    95
      }
f41884b9c4f1 actually wait for forked process and return its status -- this is not meant to be a daemon;
wenzelm
parents: 62293
diff changeset
    96
    }
50290
735bea8d89c9 more defensive retry via fork;
wenzelm
parents: 49551
diff changeset
    97
    else if (setsid() == -1) fail("Cannot set session id (after fork)");
735bea8d89c9 more defensive retry via fork;
wenzelm
parents: 49551
diff changeset
    98
  }
47764
d141f1193789 more direct bash process group invocation on Cygwin, bypassing extra sh.exe and perl.exe which tend to crash;
wenzelm
parents:
diff changeset
    99
d141f1193789 more direct bash process group invocation on Cygwin, bypassing extra sh.exe and perl.exe which tend to crash;
wenzelm
parents:
diff changeset
   100
50292
45fe12c9788e report proper pid *after* fork;
wenzelm
parents: 50290
diff changeset
   101
  /* report pid */
45fe12c9788e report proper pid *after* fork;
wenzelm
parents: 50290
diff changeset
   102
73599
981df2e1f646 clarified command-line;
wenzelm
parents: 62575
diff changeset
   103
  fprintf(stdout, "%d\n", getpid());
981df2e1f646 clarified command-line;
wenzelm
parents: 62575
diff changeset
   104
  fflush(stdout);
62292
486236dcd4d7 more flexible command-line;
wenzelm
parents: 50292
diff changeset
   105
486236dcd4d7 more flexible command-line;
wenzelm
parents: 50292
diff changeset
   106
486236dcd4d7 more flexible command-line;
wenzelm
parents: 50292
diff changeset
   107
  /* shift command line */
486236dcd4d7 more flexible command-line;
wenzelm
parents: 50292
diff changeset
   108
486236dcd4d7 more flexible command-line;
wenzelm
parents: 50292
diff changeset
   109
  int i;
73599
981df2e1f646 clarified command-line;
wenzelm
parents: 62575
diff changeset
   110
  for (i = 2; i < argc; i++) {
981df2e1f646 clarified command-line;
wenzelm
parents: 62575
diff changeset
   111
    argv[i - 2] = argv[i];
62292
486236dcd4d7 more flexible command-line;
wenzelm
parents: 50292
diff changeset
   112
  }
486236dcd4d7 more flexible command-line;
wenzelm
parents: 50292
diff changeset
   113
  argv[argc - 2] = NULL;
486236dcd4d7 more flexible command-line;
wenzelm
parents: 50292
diff changeset
   114
  argv[argc - 1] = NULL;
50292
45fe12c9788e report proper pid *after* fork;
wenzelm
parents: 50290
diff changeset
   115
45fe12c9788e report proper pid *after* fork;
wenzelm
parents: 50290
diff changeset
   116
47764
d141f1193789 more direct bash process group invocation on Cygwin, bypassing extra sh.exe and perl.exe which tend to crash;
wenzelm
parents:
diff changeset
   117
  /* exec */
d141f1193789 more direct bash process group invocation on Cygwin, bypassing extra sh.exe and perl.exe which tend to crash;
wenzelm
parents:
diff changeset
   118
62292
486236dcd4d7 more flexible command-line;
wenzelm
parents: 50292
diff changeset
   119
  execvp("bash", argv);
47796
c37411691ee7 more direct exec with synchronous exit code;
wenzelm
parents: 47764
diff changeset
   120
  fail("Cannot exec process");
47764
d141f1193789 more direct bash process group invocation on Cygwin, bypassing extra sh.exe and perl.exe which tend to crash;
wenzelm
parents:
diff changeset
   121
}