Asterisk - The Open Source Telephony Project GIT-master-a358458
Functions | Variables
astcanary.c File Reference
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <utime.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
Include dependency graph for astcanary.c:

Go to the source code of this file.

Functions

int main (int argc, char *argv[])
 

Variables

static const char explanation []
 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 immediately fall over. Seeing this, the miners could take action to escape the mine, seeing an imminent danger. More...
 

Function Documentation

◆ main()

int main ( int  argc,
char *  argv[] 
)
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.

Definition at line 92 of file astcanary.c.

93{
94 int fd;
95 pid_t parent;
96
97 if (argc < 3) {
98 fprintf(stderr, "Usage: %s <monitor-filename> <ppid>\n", argv[0]);
99 exit(1);
100 }
101
102 /* Run at normal priority */
103 setpriority(PRIO_PROCESS, 0, 0);
104
105 /*!\note
106 * See http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap03.html#tag_03_265
107 * for a justification of this approach. The PPID after the creator dies in Linux and
108 * most other Unix-like systems will be 1, but this is not strictly the case. The POSIX
109 * specification allows it to be an implementation-defined system process. However, it
110 * most certainly will not be the original parent PID, which makes the following code
111 * POSIX-compliant.
112 */
113 for (parent = atoi(argv[2]); parent == getppid() ;) {
114 /* Update the modification times (checked from Asterisk) */
115 if (utime(argv[1], NULL)) {
116 /* Recreate the file if it doesn't exist */
117 if ((fd = open(argv[1], O_RDWR | O_TRUNC | O_CREAT, 0777)) > -1) {
118 if (write(fd, explanation, strlen(explanation)) < 0) {
119 exit(1);
120 }
121 close(fd);
122 } else {
123 exit(1);
124 }
125 continue;
126 }
127
128 /* Run occasionally */
129 sleep(5);
130 }
131
132 /* Exit when the parent dies */
133 return 0;
134}
static const char explanation[]
At one time, canaries were carried along with coal miners down into a mine. Their purpose was to aler...
Definition: astcanary.c:79
#define setpriority
Definition: asterisk.h:50
#define NULL
Definition: resample.c:96

References explanation, NULL, and setpriority.

Variable Documentation

◆ explanation

const char explanation[]
static

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 immediately fall over. Seeing this, the miners could take action to escape the mine, seeing an imminent danger.

This process serves a similar purpose, though with the realtime priority being the reason. When a thread starts running away with the processor, it is typically difficult to tell what thread caused the problem, as the machine acts as if it is locked up (in fact, what has happened is that Asterisk runs at a higher priority than even the login shell, so the runaway thread hogs all available CPU time.

If that happens, this canary process will cease to get any process time, which we can monitor with a realtime thread in Asterisk. Should that happen, that monitoring thread may take immediate action to slow down Asterisk to regular priority, thus allowing an administrator to login to the system and restart Asterisk or perhaps take another course of action (such as retrieving a backtrace to let the developers know what precisely went wrong).

Note that according to POSIX.1, all threads inside a single process must share the same priority, so when the monitoring thread deprioritizes itself, it deprioritizes all threads at 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.

Definition at line 79 of file astcanary.c.

Referenced by main().