[Initng-svn] r1958 - in initng: plugins/pidfile plugins/pidfile/test src

svn at initng.thinktux.net svn at initng.thinktux.net
Sun Nov 6 20:10:43 CET 2005


Author: jimmy
Date: Sun Nov  6 20:10:31 2005
New Revision: 1958

Modified:
   initng/plugins/pidfile/initng_pidfile.c
   initng/plugins/pidfile/test/test_pidfile.ii
   initng/src/initng_handler.c
Log:
Rewrote pidfilecheck and added pidof variable, when the daemon dies, it will check for a process with a name set by pidof and use that pid for the daemon.

Also fixed so that stop_process will check if daemon is running when stopping it so it wont wait for a dead child to stop.


Modified: initng/plugins/pidfile/initng_pidfile.c
==============================================================================
--- initng/plugins/pidfile/initng_pidfile.c	(original)
+++ initng/plugins/pidfile/initng_pidfile.c	Sun Nov  6 20:10:31 2005
@@ -28,6 +28,8 @@
 #include <errno.h>
 #include <assert.h>
 #include <string.h>
+#include <sys/types.h>
+#include <dirent.h>
 #include "../../src/initng_handler.h"
 #include "../../src/initng_global.h"
 #include "../../src/initng_common.h"
@@ -35,11 +37,72 @@
 
 #include "initng_pidfile.h"
 
-
+s_entry PIDOF = { "pid_of", STRING, 6, DAEMON_OPT };
 s_entry PIDFILE = { "pid_file", STRING, 8, DAEMON_OPT };
 
-static int check_for_pidfile(active_h * s);
-static int check_on_kill(active_h * s, process_h * p);
+
+int is_ok=FALSE;
+
+static pid_t pid_of(const char *name)
+{
+    DIR *dir;
+    struct dirent *d;
+    FILE *fp;
+    pid_t pid;
+    #define BUFF_SIZE 256
+    char buf[BUFF_SIZE + 1];
+    
+    D_("Will check for: %s\n", name);
+    
+    dir=opendir("/proc");
+    if(!dir) return(-1);
+    
+    /* Walk through the directory. */
+    while ((d = readdir(dir)) != NULL)
+    {
+	char *s=NULL;
+	int len = 0;
+
+	/* See if this is a process */
+	if ((pid = atoi(d->d_name)) == 0) continue;
+
+	/* Open the status file. */
+	snprintf(buf, BUFF_SIZE, "/proc/%s/stat", d->d_name);
+
+	/* Read SID & statname from it. */
+ 	if (!(fp = fopen(buf, "r")))
+	    continue;
+	
+	buf[0] = '\0';
+	fgets(buf, BUFF_SIZE, fp);
+
+	s = buf;
+	
+	/* skip to the first space */
+	while (*s && *s != ' ')
+	    s++;
+	if(*s=='\0') continue;
+	
+	/* skip the space */
+	s++;
+	
+	/* skipp the '(' char */
+	if(*s!='(') continue;
+	s++;
+	
+	/* count the lenght */
+	while(s[len] && s[len]!=')')
+	    len++;
+	    
+	if(strncmp(s, name, len)==0) {
+	    D_("Found %s with pid %d\n", name, pid);
+	    return(pid);
+	}
+    }
+    
+    D_("Did not find a process with name %s\n", name);
+    return(-1);
+}
 
 
 /*
@@ -47,7 +110,7 @@
  * be set RUNNING if there must exist a pidfile, and
  * pid entry has to be updated.
  */
-int check_if_done(active_h * s, e_a_status status)
+int check_if_done(active_h *s, e_a_status status)
 {
     assert(s);
     assert(s->name);
@@ -58,91 +121,39 @@
     if (status != RUNNING)
         return (TRUE);
 
-    /* Make sure the service uses a pidfile */
-    if (!active_db_is(&PIDFILE, s))
-        return (TRUE);
+    if(is_ok == TRUE)
+	return(TRUE);
 
-    /* if pidfile is set, we say ok for this status change */
-    if (check_for_pidfile(s) == TRUE)
+    /* Make sure the service uses a pidfile */
+    if (active_db_is(&PIDFILE, s) || active_db_is(&PIDOF, s))
     {
-        D_("Pidfine found and new pid set.\n");
-        return (TRUE);
+	/* the service have to die, and check_on_kill have to collect the pid first */
+        return (FALSE);
     }
-
-
-    D_(" service %s is not up, it have to wait for pidfile first!\n",
-       s->name);
-
-    /* An alarm, make sure that this function will be called again */
-    alarm(1);
-
-    /* Don't allow this change, this will leave this service STARTING */
-    return (FALSE);
+    return(TRUE);
 }
 
 /*
  * Check if a pidfile exists, if it exists, update the 
  * pid in the active_db entry. and return TRUE
  */
-static int check_for_pidfile(active_h * s)
+static pid_t pid_from_file(const char *name)
 {
     int fd = 0;
     int len = 0;
-    int newpid = 0;
     char buf[21];
-    char *pidfile;
-    process_h *process = NULL;
-
-    assert(s);
-    assert(s->name);
-
-    S_;
-    if (s->type != TYPE_DAEMON)
-    {
-        F_("Only daemon can have a pidfile.\n");
-        return (FALSE);
-    }
 
-    while_processes(process, s)
-    {
-        if (process->pt == T_DAEMON)
-            break;
-
-    }
-
-    /* The start_process have to be */
-    if (!process || process->pt != T_DAEMON)
-    {
-        F_("Where is the process?\n");
-        return (FALSE);
-    }
-
-    pidfile = active_db_get_string(&PIDFILE, s);
-    if (!pidfile)
-    {
-        F_("Where is the pidfile string?\n");
-        return (FALSE);
-    }
-    D_("service %s uses pidfile \"%s\"\n", s->name, pidfile);
-
-    pidfile = fix_variables(pidfile, s);
-    if (!pidfile)
-    {
-        F_("Where is the pidfile string?\n");
-        return (FALSE);
-    }
-    D_("Also known as \"%s\"\n", pidfile);
+    assert(name);
 
     /* open pid file */
-    fd = open(pidfile, O_RDONLY);
+    fd = open(name, O_RDONLY);
 
     /* If we cant open pidfile, this is bad */
     if (fd == -1)
     {
-        D_("Unable to open pidfile: %s, \"%s\", it might not be created yet.",
-           pidfile, strerror(errno));
-        free(pidfile);
-        return (FALSE);
+        W_("Unable to open pidfile: %s, \"%s\", it might not be created yet.",
+           name, strerror(errno));
+        return (-1);
     }
 
     /* Read data from buffer */
@@ -150,9 +161,8 @@
     close(fd);
     if (len < 1)
     {
-        F_("Read 0 chars from %s, Its empty.\n", pidfile);
-        free(pidfile);
-        return (FALSE);
+        F_("Read 0 chars from %s, Its empty.\n", name);
+        return (-1);
     }
 
     /* remove last newline */
@@ -162,37 +172,54 @@
         buf[len] = 0;
 
     /* Try to convert pid to int */
-    newpid = atoi(buf);
-    if (newpid < 2)
-    {
-        F_("Failed to convert pid %s (%s) to int\n", buf, pidfile);
-        free(pidfile);
-        return (FALSE);
-    }
+    return (atoi(buf));
+}
 
-    /* Check if the old pid == newpid) */
-    if (newpid == process->pid)
-    {
-        D_("The pid in pidfile, is the same as the pid we have.\n");
-        free(pidfile);
-        return (TRUE);
-    }
+static pid_t get_pidof(active_h * s)
+{
+    pid_t pid;
+    char *pidof;
 
+    pidof=active_db_get_string(&PIDOF, s);
+    if(!pidof)
+	return(-1);
+    
+    
+    pidof=fix_variables(pidof, s);
+    if(pidof)
+	return(-1);
+	
+    pid=pid_of(pidof);
+    free(pidof);
+    return(pid);
+}
 
-    /* See if it's a valid pid */
-    if (kill(newpid, 0) < 0 && (errno == ESRCH))
-    {
-        F_("Pid %d found ( in file %s ), But there exists no process with pid %d.\n", newpid, pidfile, newpid);
-        free(pidfile);
-        return (FALSE);
-    }
+/* this will get the pid of PIDFILE entry of service */
+static pid_t get_pidfile(active_h * s)
+{
+    pid_t pid;
+    char *pidfile;
 
-    /* Finally set it!\n */
-    D_("Pid updated for %s, from %d to %d.\n", s->name, process->pid, newpid);
-    process->pid = newpid;
+    /* get the pidfile */
+    pidfile=active_db_get_string(&PIDFILE, s);
+    
+    /* check so that its found */
+    if(!pidfile)
+	return(-1);
+    
+    /* fix the variables in the string */
+    pidfile=fix_variables(pidfile, s);
+    
+    /* check so we got the string*/
+    if(!pidfile)
+	return(-1);
 
+    /* get the pid from the file */
+    pid=pid_from_file(pidfile);
     free(pidfile);
-    return (TRUE);
+    
+    /* return the pid */
+    return(pid);
 }
 
 static int check_on_kill(active_h * s, process_h * p)
@@ -201,6 +228,7 @@
     assert(s->name);
     assert(p);
 
+    pid_t pid=-1;
     S_;
 
     /* make sure its the start process this is about */
@@ -211,8 +239,39 @@
     if (s->a_status != STARTING)
         return (FALSE);
 
+    D_("will handle %s status %s\n", s->name, active_db_get_status_string(s->a_status));
+    /* if rcode indicate failure, dont check for pidfile */
+    if(p->r_code > 0)
+	return(FALSE);
+	
+    /* check if string PIDOF or PIDFILE exits */
+    if(active_db_is(&PIDOF, s))
+    {
+	D_("getting pid by PIDOF!\n");
+	/* get pid by process name */
+	pid=get_pidof(s);
+	D_("result : %d\n", pid);
+    }
+    
+    if (active_db_is(&PIDFILE, s))
+    {
+	D_("getting pid by PIDFILE!\n");
+	pid=get_pidfile(s);
+	D_("result : %d\n", pid);
+    }
+    
+    if(pid < 2)
+    {
+	return(FALSE);
+    }
+    
+    /* set the new pid, to that we got from pidof or pidfile */
+    p->pid = pid;
+    
     /* this will alter check_if_done abowe */
+    is_ok=TRUE;
     mark_service(s, RUNNING);
+    is_ok=FALSE;
     return (TRUE);
 }
 
@@ -225,8 +284,10 @@
         return (FALSE);
     }
 
+    is_ok=FALSE;
     initng_sdt_add(&PIDFILE);
-    initng_add_hook(CONFIRM_ASTATUS_CHANGE, 10, &check_if_done);
+    initng_sdt_add(&PIDOF);
+    initng_add_hook(CONFIRM_ASTATUS_CHANGE, 90, &check_if_done);
     initng_add_hook(HANDLE_KILLED, 10, &check_on_kill);
 
     return (TRUE);
@@ -236,6 +297,7 @@
 {
     D_("module_unload();\n");
     initng_sdt_del(&PIDFILE);
+    initng_sdt_del(&PIDOF);
     initng_del_hook(CONFIRM_ASTATUS_CHANGE, &check_if_done);
     initng_del_hook(HANDLE_KILLED, &check_on_kill);
 

Modified: initng/plugins/pidfile/test/test_pidfile.ii
==============================================================================
--- initng/plugins/pidfile/test/test_pidfile.ii	(original)
+++ initng/plugins/pidfile/test/test_pidfile.ii	Sun Nov  6 20:10:31 2005
@@ -1,4 +1,4 @@
-service debug/test_pidfile {
+daemon debug/test_pidfile {
     respawn = no
     daemon = /sbin/test_pidfile
     pid_file = /var/run/test.pid

Modified: initng/src/initng_handler.c
==============================================================================
--- initng/src/initng_handler.c	(original)
+++ initng/src/initng_handler.c	Sun Nov  6 20:10:31 2005
@@ -608,9 +608,30 @@
 
 static void handle_STOP_DEP_MET_daemon(active_h * service_to_stop)
 {
+    process_h *process, *safe = NULL;
+
     /* mark this service as STOPPING */
     mark_service(service_to_stop, STOPPING);
 
+    /* find the daemon, and check so it still exits */
+    while_processes_safe(process, safe, service_to_stop)
+    {
+        if (process->pt != T_DAEMON)
+            continue;
+	    
+        if (process->pid <= 0)
+	{
+            mark_service(service_to_stop, STOPPED);
+	    return;
+	}
+
+        if (kill(process->pid, 0) && errno == ESRCH)
+        {
+	    mark_service(service_to_stop, STOPPED);
+	    return;
+        }
+    }
+
     /* launch stop service */
     switch (launch(service_to_stop, T_KILL))
     {


More information about the Initng-svn mailing list