Patch: support for deleted/disabled jobs
Johan Kiviniemi
netsplit.com-upstart-devel at johan.kiviniemi.name
Sun Sep 3 16:47:26 BST 2006
Hi
I already sent this to Scott, but i thought i might as well post it
here, in case anyone's interested.
This patch adds support for deletion of jobs, i.e. when you delete a
file from /etc/event.d, upstart will kill its process (if one's running)
and then forget about the job.
It also adds support for a "disabled" stanza, which allows a sysadmin to
disable jobs easily without having to delete them. Adding the line
"disabled" to an event.d file has the same effect as deleting the file
(the file will still be parsed for valid syntax, though).
--
Jοhan Kiviniemi http://johan.kiviniemi.name/
-------------- next part --------------
=== modified file 'init/cfgfile.c'
--- init/cfgfile.c 2006-09-01 18:47:39 +0000
+++ init/cfgfile.c 2006-09-02 19:29:50 +0000
@@ -249,6 +249,13 @@
nih_list_free (&old_job->entry);
}
+ /* A "disabled" stanza was found; the job should be deleted */
+ if (job->disabled) {
+ nih_debug ("Job %s is disabled", job->name);
+ if (job_delete (job))
+ return NULL; /* Job was destroyed immediately */
+ }
+
return job;
}
@@ -350,6 +357,14 @@
_("expected version string"));
}
+ } else if (! strncmp (file + tok_start, "disabled", tok_len)) {
+ /* disabled
+ *
+ * indicates that the job should be ignored
+ */
+
+ job->disabled = TRUE;
+
} else if (! strncmp (file + tok_start, "depends", tok_len)) {
/* depends WS <job name>...
*
@@ -1646,11 +1661,15 @@
/* FIXME better name checking required */
- /* FIXME we don't handle DELETE yet ... that should probably mark
- * the running job as an instance or delete a stopped one
- */
if (events & IN_DELETE) {
- nih_debug ("Delete of %s/%s (ignored)", watch->path, name);
+ Job *job;
+
+ nih_debug ("Delete of %s/%s", watch->path, name);
+
+ job = job_find_by_name (name);
+ if (job)
+ job_delete (job);
+
return;
}
=== modified file 'init/job.c'
--- init/job.c 2006-09-01 18:47:39 +0000
+++ init/job.c 2006-09-02 19:56:38 +0000
@@ -138,6 +138,8 @@
job->author = NULL;
job->version = NULL;
+ job->disabled = 0;
+
job->goal = JOB_STOP;
job->state = JOB_WAITING;
@@ -269,6 +271,8 @@
job_change_state (Job *job,
JobState state)
{
+ int destroy = FALSE;
+
nih_assert (job != NULL);
nih_assert (job->process_state == PROCESS_NONE);
@@ -291,8 +295,9 @@
nih_assert (old_state == JOB_STOPPING);
nih_assert (job->goal == JOB_STOP);
- /* FIXME
- * instances need to be cleaned up */
+ /* instances need to be cleaned up */
+ if (job->is_instance)
+ destroy = TRUE;
NIH_MUST (event = nih_sprintf (job, "%s/stopped",
job->name));
@@ -407,6 +412,11 @@
if (job_event)
event_queue (job->name);
}
+
+ if (destroy) {
+ nih_info (_("destroying job %s"), job->name);
+ nih_list_free (&job->entry);
+ }
}
/**
@@ -826,7 +836,10 @@
* If a list of "normal" exit codes is provided, this is
* the list of exit codes that _prevent_ a respawn
*/
- if (job->respawn) {
+ if (job->disabled) {
+ nih_info (_("%s is disabled, not respawning"),
+ job->name);
+ } else if (job->respawn) {
size_t i;
for (i = 0; i < job->normalexit_len; i++)
@@ -884,6 +897,11 @@
job_init ();
+ if (job->disabled) {
+ nih_info (_("%s is disabled, not starting"), job->name);
+ return;
+ }
+
if (job->goal == JOB_START)
return;
@@ -1016,6 +1034,38 @@
/**
+ * job_delete:
+ * @job: job to be deleted.
+ *
+ * Stop and destroy the job.
+ *
+ * Returns: %TRUE if the job was destroyed immediately, %FALSE if not.
+ **/
+int
+job_delete (Job *job)
+{
+ nih_assert (job != NULL);
+
+ /* The job will be destroyed as soon as it reaches the "waiting"
+ * state */
+ job->is_instance = TRUE;
+ /* Any attempts to start or respawn the job will be prevented */
+ job->disabled = TRUE;
+
+ if (job->state == JOB_WAITING) {
+ nih_info (_("destroying job %s"), job->name);
+ nih_list_free (&job->entry);
+
+ return TRUE;
+ } else {
+ job_stop (job);
+
+ return FALSE;
+ }
+}
+
+
+/**
* job_catch_runaway
* @job: job respawning.
*
=== modified file 'init/job.h'
--- init/job.h 2006-09-01 01:14:47 +0000
+++ init/job.h 2006-09-02 19:28:21 +0000
@@ -85,6 +85,7 @@
* @name: string name of the job; namespace shared with events,
* @description: description of the job; intended for humans,
* @author: author of the job; intended for humans,
+ * @disabled: whether attempts to start or respawn the job should be prevented,
* @version: version of the job; intended for humans,
* @goal: whether the job is to be stopped or started,
* @state: actual state of the job,
@@ -136,6 +137,8 @@
char *author;
char *version;
+ int disabled;
+
JobGoal goal;
JobState state;
@@ -217,6 +220,8 @@
void job_start (Job *job);
void job_stop (Job *job);
+int job_delete (Job *job);
+
void job_release_depends (Job *job);
void job_start_event (Job *job, Event *event);
=== modified file 'init/tests/test_cfgfile.c'
--- init/tests/test_cfgfile.c 2006-08-31 21:08:56 +0000
+++ init/tests/test_cfgfile.c 2006-09-02 20:03:32 +0000
@@ -24,8 +24,10 @@
#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/wait.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <unistd.h>
@@ -55,10 +57,11 @@
int
test_read_job (void)
{
- Job *job;
- FILE *jf, *output;
- char dirname[25], filename[35], text[161];
- int ret = 0, i, oldstderr;
+ Job *job;
+ FILE *jf, *output;
+ char dirname[25], filename[35], text[161];
+ pid_t pid;
+ int ret = 0, i, oldstderr;
printf ("Testing cfg_read_job()\n");
sprintf (dirname, "/tmp/test_cfgfile.%d", getpid ());
@@ -750,6 +753,47 @@
nih_list_free (&job->entry);
+ printf ("...with disabled\n");
+ jf = fopen (filename, "w");
+ fprintf (jf, "exec /usr/bin/foo\n");
+ fprintf (jf, "disabled\n");
+ fclose (jf);
+
+ job = cfg_read_job (NULL, filename, "test");
+ if (job) {
+ printf ("BAD: job wasn't destroyed immediately.\n");
+ ret = 1;
+ }
+
+
+ printf ("...with re-reading job file that has became disabled\n");
+ job = job_new (NULL, "test");
+ job->goal = JOB_START;
+ job->state = JOB_RUNNING;
+ job->process_state = PROCESS_ACTIVE;
+ job->pid = pid = fork ();
+ if (pid == 0) {
+ select (0, NULL, NULL, NULL, NULL);
+
+ exit (0);
+ }
+
+ jf = fopen (filename, "w");
+ fprintf (jf, "exec /usr/bin/foo\n");
+ fprintf (jf, "disabled\n");
+ fclose (jf);
+
+ job = cfg_read_job (NULL, filename, "test");
+ if (! job) {
+ printf ("BAD: job was destroyed immediately.\n");
+ ret = 1;
+ } else {
+ nih_list_free (&job->entry);
+ }
+
+ waitpid (pid, NULL, 0);
+
+
printf ("...with interesting formatting\n");
jf = fopen (filename, "w");
fprintf (jf, " description \"foo\n");
=== modified file 'init/tests/test_job.c'
--- init/tests/test_job.c 2006-09-01 01:14:47 +0000
+++ init/tests/test_job.c 2006-09-02 20:47:12 +0000
@@ -3029,6 +3029,102 @@
return ret;
}
+int
+test_delete (void)
+{
+ Job *job;
+ NihTimer *timer;
+ pid_t pid;
+ int ret = 0;
+
+ printf ("Testing job_delete()\n");
+
+
+ printf ("...with waiting job\n");
+ job = job_new (NULL, "test");
+
+ was_called = 0;
+ nih_alloc_set_destructor (job, destructor_called);
+ job_delete (job);
+
+ if (! was_called) {
+ printf ("BAD: job exists after job_delete.\n");
+ ret = 1;
+ }
+
+
+ printf ("...with running job\n");
+ job = job_new (NULL, "test");
+ job->goal = JOB_START;
+ job->state = JOB_RUNNING;
+ job->process_state = PROCESS_ACTIVE;
+ job->pid = pid = fork ();
+ if (pid == 0) {
+ select (0, NULL, NULL, NULL, NULL);
+
+ exit (0);
+ }
+
+ was_called = 0;
+ nih_alloc_set_destructor (job, destructor_called);
+ job_delete (job);
+
+ if (was_called) {
+ printf ("BAD: job was destroyed immediately.\n");
+ ret = 1;
+ } else {
+ /* Job still exists, therefore we can run more tests */
+
+ if (job->is_instance != TRUE) {
+ printf ("BAD: job->is_instance isn't TRUE.\n");
+ ret = 1;
+ }
+
+ if (job->disabled != TRUE) {
+ printf ("BAD: job->disabled isn't TRUE.\n");
+ ret = 1;
+ }
+
+ /* Kill job immediately */
+ timer = job->kill_timer;
+ timer->callback (timer->data, timer);
+
+ if (! was_called) {
+ printf ("BAD: job exists after process being killed.\n");
+ ret = 1;
+ }
+ }
+
+
+ waitpid (pid, NULL, 0);
+
+ return ret;
+}
+
+int
+test_disabled (void)
+{
+ Job *job;
+ int ret = 0;
+
+ printf ("Testing disabled job\n");
+
+ job = job_new (NULL, "test");
+ job->disabled = TRUE;
+
+ job_start (job);
+
+ if (job->goal == JOB_START) {
+ printf ("BAD: job was started.\n");
+ ret = 1;
+ }
+
+ nih_list_free (&job->entry);
+
+
+ return ret;
+}
+
int
main (int argc,
@@ -3054,6 +3150,8 @@
ret |= test_detect_idle ();
ret |= test_read_state ();
ret |= test_write_state ();
+ ret |= test_delete ();
+ ret |= test_disabled ();
return ret;
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: not available
Url : https://lists.ubuntu.com/archives/upstart-devel/attachments/20060903/0bf1eca4/attachment.pgp
More information about the Upstart-devel
mailing list