[aadk-commits] dbailey: uClinux/trunk r101 - /uClinux/trunk/uClinux-dist/user/procwatch/

aadk-commits at lists.digium.com aadk-commits at lists.digium.com
Thu Dec 28 08:04:37 MST 2006


Author: dbailey
Date: Thu Dec 28 09:04:36 2006
New Revision: 101

URL: http://svn.digium.com/view/aadk?view=rev&rev=101
Log:
Adding program that monitors a set of processes and hits the watchdog while they are still active

Added:
    uClinux/trunk/uClinux-dist/user/procwatch/
    uClinux/trunk/uClinux-dist/user/procwatch/Makefile   (with props)
    uClinux/trunk/uClinux-dist/user/procwatch/procwatch.c   (with props)

Added: uClinux/trunk/uClinux-dist/user/procwatch/Makefile
URL: http://svn.digium.com/view/aadk/uClinux/trunk/uClinux-dist/user/procwatch/Makefile?view=auto&rev=101
==============================================================================
--- uClinux/trunk/uClinux-dist/user/procwatch/Makefile (added)
+++ uClinux/trunk/uClinux-dist/user/procwatch/Makefile Thu Dec 28 09:04:36 2006
@@ -1,0 +1,15 @@
+
+EXEC = procwatch
+OBJS = procwatch.o
+
+all: $(EXEC)
+
+$(EXEC): $(OBJS)
+	$(CC) $(LDFLAGS) -o $@ $(OBJS) $(LDLIBS$(LDLIBS_$@))
+
+romfs:
+	$(ROMFSINST) /bin/$(EXEC)
+
+clean:
+	-rm -f $(EXEC) *.elf *.gdb *.o
+

Propchange: uClinux/trunk/uClinux-dist/user/procwatch/Makefile
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: uClinux/trunk/uClinux-dist/user/procwatch/Makefile
------------------------------------------------------------------------------
    svn:executable = *

Propchange: uClinux/trunk/uClinux-dist/user/procwatch/Makefile
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: uClinux/trunk/uClinux-dist/user/procwatch/procwatch.c
URL: http://svn.digium.com/view/aadk/uClinux/trunk/uClinux-dist/user/procwatch/procwatch.c?view=auto&rev=101
==============================================================================
--- uClinux/trunk/uClinux-dist/user/procwatch/procwatch.c (added)
+++ uClinux/trunk/uClinux-dist/user/procwatch/procwatch.c Thu Dec 28 09:04:36 2006
@@ -1,0 +1,275 @@
+/*
+ * procwatch - Process monitor using Standard Linux Watchdog API
+ *
+ * Copyright (C) 2006, Digium, Inc.
+ *
+ * Doug Bailey <dbailey at digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. 
+ */
+
+#include <dirent.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <asm/page.h>
+#include <linux/version.h>
+#include <linux/watchdog.h>
+
+#define MAX_PROC_NAME_SIZE	256
+#define MAX_PROCESS			32
+#define DEFAULT_SLEEP_VAL 	(2000)
+
+#define STATUS_LINE_ARG		"Name:"
+		
+/*** Local Prototypes ***/
+static void show_usage(void);
+
+		
+struct app_monitor {
+		char * name;
+		int valid;
+		int online;
+};
+
+int main(int argc, char ** argv)
+{
+	struct app_monitor proc_monitor[MAX_PROCESS];
+	int 			num_to_monitor = 0; 
+	unsigned long 	sleep_val = DEFAULT_SLEEP_VAL; 
+	unsigned long 	new_sleep;
+	int 			watchdog_time = 0;
+	int 			fd_watchdog;
+	char 			* dummy;
+	int				opt;
+	int 			daemon = 0;
+	pid_t 			pid, sid;
+		
+	opterr = 0;
+	while ((opt = getopt(argc, argv, "?dp:t:w:")) > 0) {
+		switch (opt) {
+			case 'p':
+				proc_monitor[num_to_monitor].name 	= optarg;
+				proc_monitor[num_to_monitor].valid 	= 0;
+				proc_monitor[num_to_monitor].online = 0;
+				num_to_monitor++;
+				break;
+			case 't':
+				new_sleep = strtoul(optarg, &dummy, 10);
+				if(0 < new_sleep) {
+					sleep_val = new_sleep;
+				}
+				break;
+			case 'w':
+				watchdog_time = atoi(optarg);
+				break;
+			case 'd':
+				daemon = 1;
+				break;
+			default:
+				show_usage();
+				exit(EXIT_SUCCESS);
+		}
+	}
+	
+    if(daemon){	/*NOTE uClinux does not support fork - Save it for later*/
+		/* Fork off process */
+		pid = fork();
+		if (pid < 0) {
+			perror("Cannot Fork child process\n");
+			exit(EXIT_FAILURE);
+		}
+        /* If we got a good PID, then
+			we can exit the parent process. */
+		else if (pid > 0) {
+			exit(EXIT_SUCCESS);
+		}
+
+		/* Change the file mode mask */
+		umask(0);
+
+		/* new SID for the child process */
+		sid = setsid();
+		if (sid < 0) {
+			perror("Cannot set the Wathcdog Monitor child SID \n");
+			_exit(EXIT_FAILURE);
+		}
+	}
+	
+	fd_watchdog = open("/dev/watchdog", O_RDWR);
+
+	if (fd_watchdog == -1) {
+		printf("Cannot open the watchdog timer\n");
+		_exit(1);
+	}
+
+	if(0 < watchdog_time) {
+		ioctl(fd_watchdog, WDIOC_SETTIMEOUT, &watchdog_time);
+		printf("The watchdog timeout has been set to %d seconds\n", watchdog_time);
+	}
+	
+	while(1){
+		if(0 == find_processes(proc_monitor, num_to_monitor)){
+			write(fd_watchdog, "\0", 1);
+		}
+		// Sleep between checking for processes
+		usleep(1000 * sleep_val);
+	}
+	
+	return 0;
+}
+
+/* Display command line usage */
+static void show_usage(void)
+{
+	printf("procwatch - Watchdog monitor for one or more processes\n");  
+	printf("Usage: \n");  
+	printf("procwatch [-t <time in mS>] [-w <watchdog timer value in seconds>] [-p <process name>] [-d] \n");  
+	printf("\t\t-t - specified time to sleep between checks (in milliseconds)\n");  
+	printf("\t\t-w - specified time for the watchdog to timeout (in seconds)\n");  
+	printf("\t\t-p - specific process name to monitor.  Program waits for the process to become active.\n");
+	printf("\t\t     After the program is active, it must stay alive for the watchdog to be refreshed.\n"); 
+	printf("\t\t     There can be multiple processes monitored by the program.\n"); 
+	printf("\t\t-d - run the program as a daemon. (Not supported under uClinux.)\n");
+	printf("\t\t-? - See this usage.\n");
+	
+}
+
+/* 
+ * Finds whether the list of processes passed to the function are currently active. 
+ * The function uses the proc file system to find the active processes. 
+ * 
+ * The it looks at the Name field in the /proc/<id>/status file for the 
+ * desired process name.  
+ */
+
+int find_processes(struct app_monitor *list, int list_len)
+{
+	int unfound_process;
+	int offline_process;
+
+	DIR    			*dir;
+	int 			pid;
+	int 			valid_line;
+	int				x, y, n;
+	struct dirent 	*entry;
+	FILE 			*fp;
+	char 			*proc_id_name;
+	char 			*cmd_line;
+	char 			status[128];
+	char 			buf[128];
+
+	if(0 == list_len) {
+		return 0;
+	} else if( 0 > list_len) {
+		return -1;
+	}
+	
+	dir = opendir("/proc");
+	if(!dir)
+		return -1; 
+	
+	/* Initialize the list to all invalid processes */
+	for(n = 0, unfound_process = 0, offline_process = 0; n < list_len; n++){
+		list[n].valid = 0; 	
+		if(0 != list[n].online){	/* This process is online, we must find it in proc */
+			unfound_process++;
+		} else {
+			offline_process++;
+		}
+		
+	}
+		
+/* while I have not accounted for all the processes I need to check */
+	while(0 < unfound_process || 0 < offline_process) {
+		if((entry = readdir(dir)) == NULL) {
+			/* cannot read more entries, time to get out */
+			closedir(dir);
+			dir = NULL;
+			break; 
+		}
+		proc_id_name = entry->d_name;
+		if (!(*proc_id_name >= '0' && *proc_id_name <= '9')) {/* look for decimal numeric name */
+			continue;
+		}
+		pid = atoi(proc_id_name);
+		if(0 >= pid) {
+			continue;
+		}			
+		
+		buf[0] = '\0';	/* Insure termination of string */
+		sprintf(status, "/proc/%d/status", pid);
+		if((fp = fopen(status, "r")) == NULL){
+			continue;
+		}
+		
+		/* Find the Name line in the status file */
+		n = 0;
+		valid_line = 0;
+		while(0 != valid_line || !feof(fp)) {
+			/* Append data from the file into the raw buffer */
+			if((x=fread(&buf[n], 1, sizeof(buf)-1-n, fp)) > 0) {
+				n = x+n;
+			}
+			/* extract a terminated line from the buffer */
+			for(valid_line = 0, x = 0; x < n && x < 128; x++) {
+				if(buf[x] == '\n' || buf[x] == '\r' ) { 
+					status[x] = '\0';
+					valid_line = 1;
+					x++;
+					for(y = 0; x < n; y++, x++) {
+						buf[y] = buf[x];
+					} 
+					n = y;
+					buf[n] = '\0';
+					break;
+				} else if( ' ' > buf[x]) {
+					status[x] = ' '; 
+				} else {
+					status[x] = buf[x]; 
+				}
+			}
+			/* see if this line starts with the desired line header*/
+			if(valid_line) {
+				/* set cmd_line to point to string after header name */
+				if(NULL != (cmd_line= strstr( status, STATUS_LINE_ARG))) {
+					cmd_line += strlen(STATUS_LINE_ARG);
+					break;
+				} 
+			} else {
+				cmd_line = NULL;
+			}
+		}
+		fclose(fp);
+		
+		/* Is the name in the list of processes to look for */ 
+		if(cmd_line != NULL) {
+			for(n = 0; n < list_len; n++) {
+				/* If we have found this process */
+				if(NULL != strstr( cmd_line, list[n].name)){
+					/* first test if the process has come online, if so markit as such */
+					if(0 == list[n].online){
+						list[n].online = 1;
+						list[n].valid = 1;	/* Mark that I checked this one */
+						offline_process--;
+						/* If it is already online and has not been marked, then mark it */
+					} else if(0 == list[n].valid){
+						unfound_process--;
+						list[n].valid = 1;
+					}
+				}
+			}
+		}
+	}
+	return unfound_process;
+}	
+

Propchange: uClinux/trunk/uClinux-dist/user/procwatch/procwatch.c
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: uClinux/trunk/uClinux-dist/user/procwatch/procwatch.c
------------------------------------------------------------------------------
    svn:mime-type = text/plain



More information about the aadk-commits mailing list