9

How do I monitor a number of processes and if one process ends, I would like to run some code.

I have found several examples which used polling to achieve this but I am looking for a method to get pushed (probably by the OS) when a process dies. Is this possible with C or C++? It should run on any modern Linux.

If there is any chance, I would like to do that without needing root privileges.

EDIT:

The job of this whole program is to monitor these processes and send this information to another server where it gets integrated into a website.

I have not started these processes but I could ensure that they are started as the same user.

I thought it should be possible because the top / ps command under Linux also gives you information about processes you haven't started.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Ka Rl
  • 517
  • 8
  • 15
  • 2
    The question should be "is this possible with Linux". The C part won't be a problem then. – deviantfan Jan 14 '16 at 22:00
  • 1
    About root: Are you okay with getting notified only about your users processes? (I don't even know if such a notification is possible at all, but if it is, I'm sure only root can do it for *all* processes) – deviantfan Jan 14 '16 at 22:01
  • Do you have the pids of the processes to watch? Or how do you identify the set of processes to watch? – Ctx Jan 14 '16 at 22:06
  • 2
    I doubt anyone uses polling to find whether a process has terminated. `wait()` or `sigaction() /w SIGCHLD`. – EOF Jan 14 '16 at 22:08
  • 1
    Look at http://stackoverflow.com/a/28602298/3134621 – deviantfan Jan 14 '16 at 22:09
  • 3
    @EOF This can only be performed for childprocesses, not in general – Ctx Jan 14 '16 at 22:09
  • 1
    @Ctx: Then the monitored processes should be spawned by the monitoring process. That doesn't seem particularly onerous. – EOF Jan 14 '16 at 22:11
  • @EOF please don't single-handedly change the premises of the question, this might not be possible – Ctx Jan 14 '16 at 22:15
  • You might want to let us know in broader terms what it is that you are trying to do and add more details about your environment. E.g. are you trying to build a process monitor? Can you control how that process is launched? Do you have access to its source code? What are your performance/latency requirements? – thkala Jan 14 '16 at 22:55
  • 1
    @OP: *Did* you start these processes from within this one? The answer changes completely depending on whether you did or didn't. – user207421 Jan 14 '16 at 23:25
  • I added some information – Ka Rl Jan 15 '16 at 07:23
  • What exactly are the monitored processes? How and by whom are they started? Could you slightly change their program (or wrap it in some C program of yours)? Please improve your question – Basile Starynkevitch Jan 15 '16 at 08:00

3 Answers3

8

In general on Linux you can't be notified (with waitpid(2) or SIGCHLD -see signal(7)- ...) about non-child processes, or processes outside of your process group or session.

And on some Linux your (non-root) process might not even be allowed to query the existence of other processes.

Of course, there is /proc/ (having one numerical-named directory per process, e.g. /proc/1234/ for process of pid 1234, see proc(5)) that you might regularly scan (e.g. with readdir(3)...) but you cannot be notified (see inotify(7), which does not work for pseudo-file systems like /proc/ ...) about changes inside it. Notice that /proc/ is a pseudo file system, and accessing it does not involve any disk IO so is quite quick.

So what you could do is scan /proc/ every few seconds using opendir(3), readdir, closedir(3), sleep(3) in a loop. BTW, that in theory is not fail-proof (in principle, not in practice, the kernel might reuse the same pid within a few seconds), and probably won't catch all short-living processes (such as ls shell commands).

Such a periodic scan of /proc is very probably what the top(1) utility is doing. You could check that by diving into the source code of top or by strace(1)-ing it.

If your C code knows already the pid of some process and simply wants to check the existence of that process, it can use kill(2) with a signal number 0.

See also systemd & credentials(7).

If you can change the code of the monitored programs or replace them (e.g. by your small C program wrapping them) things are very different; e.g. you could replace /usr/bin/foo with /usr/local/bin/foo-wrapper and code a foo-wrapper.c which fork-s & exec-s the original /usr/bin/foo then waitpid(2) on it and finally send(2) or write(2) some message on some socket(7) or fifo(7) or pipe(7), and use a poll(2) based event loop in your monitor. If you can get all the programs fork-ed by your monitor things are also different (use waitpid...). See my execicar.c program for inspiration.

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
4

You can configure auditd daemon to create audit records (log lines) when a process ends. And then monitor auditd log file with inotify.

Provided you have access to auditd configuration and its log file.

Maxim Egorushkin
  • 131,725
  • 17
  • 180
  • 271
-3

note that the /proc/ directory holds a directory for each running process' PID for example /proc/1 is PID 1

under that directory there's the cmdline file which can be used to determine the PID's command, i.e: cat /proc/1/cmdline /usr/lib/systemd/systemd

you can traverse the /proc/[09]* irectories looking for a cmdline that matches what you are looking for, when you match that command you can simply check if the cmdline still matches the original one(the same PID can be used for another process if it had terminated

here's a simple piece of code that gets that job done: I haven't written most of the error correction(program crashes if the application isn't found, some other errors that cause segfault) #include #include #include

int main(int argc, char* argv[]) {
  if (argc != 2){
    printf("usage:\nproc <processname>\n");
    return 2;
  }
  char * processName = argv[1];
  int pid = 0;
  FILE *processFile;
  char *monitoredProcess;
  DIR *root;
  struct dirent *dir;
  root = opendir("/proc/");
if (root)
  {
    int reading = 0;
    while((dir=readdir(root))!=NULL && reading==0)
    {
     // printf("dir name:%i\n",dir->d_ino);
      if (dir->d_name[0] > 47 && dir->d_name[0] < 58) {
    char directory[128];
    strcpy(directory,"/proc/");
        strcat(directory,dir->d_name);
    strcat(directory,"/cmdline");
    processFile = fopen(directory,"r");
    if (processFile == NULL) {
      printf("Error");
      return 1;
    }
    char line[2048];
    while (fgets(line, sizeof line, processFile) != NULL) {
      if(strstr(line,processName)) {
        printf("%s\n",directory);
        monitoredProcess = directory;
        reading = 1;
      }
      //the pid has been determined at this point, now to monitor
    }
      }
    }
    //monitoring
    printf("monitoring %s\n",monitoredProcess);
    while(processFile=fopen(monitoredProcess,"r")) {
      char line[2048];
      while (fgets(line, sizeof line, processFile) != NULL) {
    if(strstr(line,processName) == NULL)
      printf("application terminated\n");
      }
      sleep(3);
      fclose(processFile);
    }
  } else
    printf("unable to open folder\n");
}
Adel Ahmed
  • 638
  • 7
  • 24
  • This is polling, which the OP already states having code for. The question is if *notification* is possible. – nobody Jan 15 '16 at 01:20