[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