Replace ast_log(LOG_DEBUG, ...) with ast_debug()
[asterisk/asterisk.git] / utils / astcanary.c
index da91e6d..8cfa3fe 100644 (file)
 #include <unistd.h>
 #include <stdlib.h>
 #include <string.h>
+#include <stdio.h>
 
 /*!\brief
  * At one time, canaries were carried along with coal miners down
  * into a mine.  Their purpose was to alert the miners when they
  * had drilled into a pocket of methane gas or another noxious
- * substance.  The canary, being the most sensitive animal would
+ * substance.  The canary, being the most sensitive animal, would
  * immediately fall over.  Seeing this, the miners could take
  * action to escape the mine, seeing an imminent danger.
  *
  * the same time.  This is also why this canary must exist as a
  * completely separate process and not simply as a thread within
  * Asterisk itself.
+ *
+ * Quote:
+ * "The nice value set with setpriority() shall be applied to the
+ * process. If the process is multi-threaded, the nice value shall
+ * affect all system scope threads in the process."
+ *
+ * Source:
+ * http://www.opengroup.org/onlinepubs/000095399/functions/setpriority.html
+ *
+ * In answer to the question, what aren't system scope threads, the
+ * answer is, in Asterisk, nothing.  Process scope threads are the
+ * alternative, but they aren't supported in Linux.
  */
 
 static const char explanation[] =
@@ -75,9 +88,25 @@ static const char explanation[] =
 int main(int argc, char *argv[])
 {
        int fd;
+       pid_t parent;
+
+       if (argc < 3) {
+               fprintf(stderr, "Usage: %s <monitor-filename> <ppid>\n", argv[0]);
+               exit(1);
+       }
+
        /* Run at normal priority */
        setpriority(PRIO_PROCESS, 0, 0);
-       for (;;) {
+
+       /*!\note
+        * See http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap03.html#tag_03_265
+        * for a justification of this approach.  The PPID after the creator dies in Linux and
+        * most other Unix-like systems will be 1, but this is not strictly the case.  The POSIX
+        * specification allows it to be an implementation-defined system process.  However, it
+        * most certainly will not be the original parent PID, which makes the following code
+        * POSIX-compliant.
+        */
+       for (parent = atoi(argv[2]); parent == getppid() ;) {
                /* Update the modification times (checked from Asterisk) */
                if (utime(argv[1], NULL)) {
                        /* Recreate the file if it doesn't exist */
@@ -96,7 +125,7 @@ int main(int argc, char *argv[])
                sleep(5);
        }
 
-       /* Never reached */
+       /* Exit when the parent dies */
        return 0;
 }