From: Thibault Godouet Date: Thu, 15 Jun 2000 20:10:11 +0000 (+0000) Subject: optimizations X-Git-Tag: ver2_9_4~701 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2c74035623ae57736e2857ad3f7b120cde3beebd;p=thirdparty%2Ffcron.git optimizations --- diff --git a/conf.c b/conf.c index f89df15..ef7deff 100644 --- a/conf.c +++ b/conf.c @@ -22,7 +22,7 @@ * `LICENSE' that comes with the fcron source distribution. */ - /* $Id: conf.c,v 1.6 2000-06-11 13:17:29 thib Exp $ */ + /* $Id: conf.c,v 1.7 2000-06-15 20:10:11 thib Exp $ */ #include "fcron.h" @@ -458,23 +458,15 @@ read_file(const char *file_name, CF *cf) /* check if the task has not been stopped during execution */ if (cl->cl_pid > 0) { - if (cl->cl_mailpid > 0) { - /* job has terminated normally, but mail has not - * been sent */ - warn("output of job '%s' has not been mailed " - "due to daemon's stop", cl->cl_shell); - cl->cl_pid = cl->cl_mailfd = cl->cl_mailpid = 0; - } else { - /* job has been stopped during execution : - * launch it again */ - warn("job '%s' has not terminated : will be executed" - " again now.", cl->cl_shell); - /* we don't set cl_nextexe to 0 because this value is - * reserved to the entries based on frequency */ - cl->cl_nextexe = 1; - insert_nextexe(cl); - cl->cl_pid = cl->cl_mailfd = cl->cl_mailpid = 0; - } + /* job has been stopped during execution : + * launch it again */ + warn("job '%s' has not terminated : will be executed" + " again now.", cl->cl_shell); + /* we don't set cl_nextexe to 0 because this value is + * reserved to the entries based on frequency */ + cl->cl_nextexe = 1; + insert_nextexe(cl); + cl->cl_pid = 0; } diff --git a/database.c b/database.c index b34bd01..9b106b8 100644 --- a/database.c +++ b/database.c @@ -22,7 +22,7 @@ * `LICENSE' that comes with the fcron source distribution. */ - /* $Id: database.c,v 1.8 2000-06-11 13:18:35 thib Exp $ */ + /* $Id: database.c,v 1.9 2000-06-15 20:12:38 thib Exp $ */ #include "fcron.h" @@ -72,17 +72,14 @@ wait_chld(void) int status; //////// - debug("wait_chld"); +// debug("wait_chld"); /////// while ( (pid = wait3(&status, WNOHANG, NULL)) > 0 ) { for (j = exe_base; j != NULL ; j = j->j_next) { if (pid < 0 || pid == j->j_line->cl_pid) { - end_job(j->j_line, status); - goto nextloop; - } - else if ( pid == j->j_line->cl_mailpid ) { - end_mailer(j->j_line, status); + j->j_line->cl_pid = 0; + j->j_line->cl_file->cf_running -= 1; /* remove file from exe list */ if (jprev != NULL) @@ -115,11 +112,9 @@ wait_all(int *counter) while ( (*counter > 0) && (pid = wait3(&status, 0, NULL)) > 0 ) { for (j = exe_base; j != NULL ; j = j->j_next) { if (pid < 0 || pid == j->j_line->cl_pid) { - end_job(j->j_line, status); - goto nextloop; - } - else if ( pid == j->j_line->cl_mailpid ) { - end_mailer(j->j_line, status); + + j->j_line->cl_pid = 0; + j->j_line->cl_file->cf_running -= 1; /* remove file from exe list */ if (jprev != NULL) diff --git a/fcron.c b/fcron.c index 4c76511..64dee66 100644 --- a/fcron.c +++ b/fcron.c @@ -21,11 +21,11 @@ * `LICENSE' that comes with the fcron source distribution. */ - /* $Id: fcron.c,v 1.11 2000-06-11 13:18:55 thib Exp $ */ + /* $Id: fcron.c,v 1.12 2000-06-15 20:12:57 thib Exp $ */ #include "fcron.h" -char rcs_info[] = "$Id: fcron.c,v 1.11 2000-06-11 13:18:55 thib Exp $"; +char rcs_info[] = "$Id: fcron.c,v 1.12 2000-06-15 20:12:57 thib Exp $"; void main_loop(void); void info(void); @@ -314,8 +314,8 @@ main(int argc, char **argv) /* parse options */ - if (strrchr(argv[0],'/')==NULL) prog_name = argv[0]; - else prog_name = strrchr(argv[0],'/')+1; + if ( strrchr(argv[0], '/') == NULL) prog_name = argv[0]; + else prog_name = strrchr(argv[0], '/') + 1; daemon_uid = getuid(); @@ -432,7 +432,6 @@ void main_loop() /* main loop - get the time to sleep until next job execution, * sleep, and then test all jobs and execute if needed. */ { - extern time_t begin_sleep; /* time at the beginning of sleeping */ time_t save; /* time remaining until next save */ struct timeval tv; /* we use usec field to get more precision */ time_t stime = 0; /* time to sleep until next job @@ -440,7 +439,7 @@ void main_loop() debug("Entering main loop"); - now = begin_sleep = time(NULL); + now = time(NULL); synchronize_dir("."); @@ -450,20 +449,14 @@ void main_loop() stime = time_to_sleep(save); for (;;) { - + sleep(stime - 1); gettimeofday(&tv, NULL); usleep( 1000000 - tv.tv_usec ); - now = time(NULL); - if (sig_chld > 0) { - - /* sleep has been stopped too early : - * sleep the remaining time */ wait_chld(); sig_chld = 0; - } else if (sig_conf > 0) { @@ -477,9 +470,9 @@ void main_loop() sig_conf = 0; } else { - debug("\n"); - debug("slept: %lds", now - begin_sleep); + + now = time(NULL); test_jobs(now); @@ -493,13 +486,6 @@ void main_loop() stime = time_to_sleep(save); - begin_sleep = now; - - if ( sig_chld == 1 ) { - wait_chld(); - sig_chld = 0; - } - } } diff --git a/fcron.h b/fcron.h index e5bf2b2..c9e59c7 100644 --- a/fcron.h +++ b/fcron.h @@ -21,7 +21,7 @@ * `LICENSE' that comes with the fcron source distribution. */ - /* $Id: fcron.h,v 1.6 2000-06-11 13:18:58 thib Exp $ */ + /* $Id: fcron.h,v 1.7 2000-06-15 20:16:38 thib Exp $ */ #ifndef __FCRONH__ #define __FCRONH__ @@ -94,8 +94,6 @@ extern void save_file(CF *file_name, char *path); /* job.c */ extern void run_job(CL *line); -extern void end_job(CL *line, int status); -extern void end_mailer(CL *line, int status); /* end of job.c */ diff --git a/global.h b/global.h index c93d35a..9ba5171 100644 --- a/global.h +++ b/global.h @@ -21,7 +21,7 @@ * `LICENSE' that comes with the fcron source distribution. */ - /* $Id: global.h,v 1.6 2000-06-11 13:19:01 thib Exp $ */ + /* $Id: global.h,v 1.7 2000-06-15 20:17:52 thib Exp $ */ /* @@ -57,7 +57,7 @@ #include "option.h" -#define FILEVERSION "003" /* syntax's version of fcrontabs : +#define FILEVERSION "004" /* syntax's version of fcrontabs : * must have a length of 3 characters */ @@ -73,7 +73,6 @@ #define debug if(debug_opt) Debug - typedef struct env_t { char *e_name; /* env name */ char *e_val; /* env value */ @@ -85,7 +84,6 @@ typedef struct CF { struct CL *cf_line_base; char *cf_user; /* user-name */ char *cf_mailto; /* mail output's to mail_user */ - short int cf_mailpos; /* 'empty mail file' size */ struct env_t *cf_env_base; /* list of all env variables to set */ int cf_running; /* number of jobs running */ } CF; @@ -98,8 +96,6 @@ typedef struct CL { char option; /* options for that line (see option.h) */ char *cl_shell; /* shell command */ pid_t cl_pid; /* running pid, 0, or armed (-1) */ - pid_t cl_mailpid; /* mailer pid or 0 */ - int cl_mailfd; /* running pid is for mail */ time_t cl_nextexe; /* time and date of the next execution */ short int cl_remain; /* remaining until next execution */ time_t cl_timefreq; /* Run every n seconds */ diff --git a/job.c b/job.c index acc8f25..7df3eb3 100644 --- a/job.c +++ b/job.c @@ -22,14 +22,17 @@ * `LICENSE' that comes with the fcron source distribution. */ - /* $Id: job.c,v 1.7 2000-06-11 13:19:17 thib Exp $ */ + /* $Id: job.c,v 1.8 2000-06-15 20:18:15 thib Exp $ */ #include "fcron.h" int temp_file(void); void xwrite(int fd, char *string); -void launch_mailer(CL *line); +void launch_mailer(CL *line, int mailfd); int change_user(const char *user, short dochdir); +void sig_dfl(void); +void end_job(CL *line, int status, int mailfd, short mailpos); +void end_mailer(CL *line, int status); int @@ -70,6 +73,15 @@ change_user(const char *user, short dochdir) } +void +sig_dfl(void) + /* set signals handling to its default */ +{ + signal(SIGTERM, SIG_DFL); + signal(SIGCHLD, SIG_DFL); + signal(SIGHUP, SIG_DFL); + signal(SIGUSR1, SIG_DFL); +} void run_job(CL *line) @@ -77,40 +89,36 @@ run_job(CL *line) { pid_t pid = 0; - char *shell = NULL; - char *home = NULL; - env_t *env = NULL; struct job *j = NULL; - /* create temporary file for stdout and stderr of the job */ - line->cl_mailfd = temp_file(); - - /* write mail header */ - xwrite(line->cl_mailfd,"To: "); - xwrite(line->cl_mailfd, line->cl_file->cf_user); - xwrite(line->cl_mailfd, "\nSubject: Output of fcron job: '"); - xwrite(line->cl_mailfd, line->cl_shell); - xwrite(line->cl_mailfd,"'\n\n"); - if ( ! line->cl_file->cf_mailpos ) - line->cl_file->cf_mailpos = ( lseek(line->cl_mailfd, 0, SEEK_END) - - strlen(line->cl_shell) ); - - /* append job to the list of executed job */ Alloc(j, job); j->j_line = line; j->j_next = exe_base; exe_base = j; + /* prepare the job execution */ switch ( pid = fork() ) { + case -1: + error_e("Fork error : could not exec '%s'", line->cl_shell); + break; case 0: /* child */ + { + char *shell = NULL; + char *home = NULL; + env_t *env = NULL; + int mailfd = 0; + short int mailpos = 0; /* 'empty mail file' size */ + int status = 0; foreground = 0; if (change_user(line->cl_file->cf_user, 1) < 0) return ; + sig_dfl(); + /* stdin is already /dev/null, setup stdout and stderr */ if ( close(1) != 0 ) die_e("Can't close file descriptor %d",1); @@ -120,14 +128,26 @@ run_job(CL *line) if ( line->cl_file->cf_mailto != NULL && strcmp(line->cl_file->cf_mailto, "") == 0 ) { - if ( close(line->cl_mailfd) != 0 ) - die_e("Can't close file descriptor %d", line->cl_mailfd); - if ( (line->cl_mailfd = open("/dev/null", O_RDWR)) < 0 ) + if ( close(mailfd) != 0 ) + die_e("Can't close file descriptor %d", mailfd); + if ( (mailfd = open("/dev/null", O_RDWR)) < 0 ) die_e("open: /dev/null:"); } + else { + /* create temporary file for stdout and stderr of the job */ + mailfd = temp_file(); + + /* write mail header */ + xwrite(mailfd,"To: "); + xwrite(mailfd, line->cl_file->cf_user); + xwrite(mailfd, "\nSubject: Output of fcron job: '"); + xwrite(mailfd, line->cl_shell); + xwrite(mailfd,"'\n\n"); + mailpos = ( lseek(mailfd, 0, SEEK_END) - strlen(line->cl_shell) ); + } - if (dup2(line->cl_mailfd, 1) != 1 || dup2(line->cl_mailfd, 2) != 2) + if (dup2(mailfd, 1) != 1 || dup2(mailfd, 2) != 2) die_e("dup2() error"); /* dup2 also clears close-on-exec flag */ foreground = 1; @@ -155,36 +175,51 @@ run_job(CL *line) shell = SHELL; } + + /* now, run the job */ + switch ( fork() ) { + case -1: + error_e("Fork error : could not exec '%s'", line->cl_shell); + break; + + case 0: + /* child */ + #ifdef CHECKJOBS - /* this will force to mail a message containing at least the exact - * and complete command executed for each execution of all jobs */ - debug("Execing '%s -c %s'", shell, line->cl_shell); + /* this will force to mail a message containing at least the exact + * and complete command executed for each execution of all jobs */ + debug("Execing '%s -c %s'", shell, line->cl_shell); #endif /* CHECKJOBS */ - execl(shell, shell, "-c", line->cl_shell, NULL); + execl(shell, shell, "-c", line->cl_shell, NULL); - /* execl returns only on error */ - die_e("execl() '%s -c %s' error", shell, line->cl_shell); + /* execl returns only on error */ + die_e("execl() '%s -c %s' error", shell, line->cl_shell); - /* execution never gets here */ + /* execution never gets here */ - case -1: - error_e("Fork error : could not exec '%s'", line->cl_shell); - break; + default: + /* parent */ + /* we use a while because an possible interruption by a signal */ + while ( (pid = wait3(&status, 0, NULL)) > 0) { + end_job(line, status, mailfd, mailpos); + + /* execution never gets here */ + + } + + } + } default: /* parent */ //////// - debug("run job - parent"); +// debug("run job - parent"); //////// line->cl_pid = pid; - //////////// - debug(" cf_running: %d", line->cl_file->cf_running); - /////////// - line->cl_file->cf_running += 1; explain(" Job `%s' started (pid %d)", line->cl_shell, line->cl_pid); @@ -194,7 +229,7 @@ run_job(CL *line) } void -end_job(CL *line, int status) +end_job(CL *line, int status, int mailfd, short mailpos) /* if task have made some output, mail it to user */ { @@ -205,8 +240,7 @@ end_job(CL *line, int status) debug(" end_job"); ////// - if ( ( lseek(line->cl_mailfd, 0, SEEK_END) - strlen (line->cl_shell) ) - > line->cl_file->cf_mailpos ) { + if ( ( lseek(mailfd, 0, SEEK_END) - strlen (line->cl_shell) ) > mailpos ){ if ( line->cl_file->cf_mailto != NULL && line->cl_file->cf_mailto[0] == '\0' ) /* there is a mail output, but it will not be mail */ @@ -231,23 +265,18 @@ end_job(CL *line, int status) else /* is this possible? */ error("Job `%s' terminated abnormally %s", line->cl_shell, m); - if (mail_output == 1) launch_mailer(line); + if (mail_output == 1) launch_mailer(line, mailfd); /* if MAILTO is "", temp file is already closed */ - if ( mail_output != 2 && close(line->cl_mailfd) != 0 ) - die_e("Can't close file descriptor %d", line->cl_mailfd); - - line->cl_pid = 0; + if ( mail_output != 2 && close(mailfd) != 0 ) + die_e("Can't close file descriptor %d", mailfd); - //////////// - debug(" cf_running: %d", line->cl_file->cf_running); - - line->cl_file->cf_running -= 1; + exit(0); } void -launch_mailer(CL *line) +launch_mailer(CL *line, int mailfd) /* mail the output of a job to user */ { char *mailto = NULL; @@ -255,70 +284,28 @@ launch_mailer(CL *line) //////// debug(" launch mailer"); //////// - switch ( line->cl_mailpid = fork() ) { - case 0: - /* child */ - foreground = 0; + foreground = 0; - /* set stdin to the job's output */ - if ( close(0) != 0 ) - die_e("Can't close file descriptor %d",0); - + /* set stdin to the job's output */ + if ( close(0) != 0 ) + die_e("Can't close file descriptor %d",0); - if (dup2(line->cl_mailfd,0)!=0) die_e("Can't dup2()"); - if (lseek(0,0,SEEK_SET)!=0) die_e("Can't lseek()"); + if (dup2(mailfd,0)!=0) die_e("Can't dup2()"); + if (lseek(0,0,SEEK_SET)!=0) die_e("Can't lseek()"); - xcloselog(); + xcloselog(); - /* determine which will be the mail receiver */ - if ( (mailto = line->cl_file->cf_mailto) == NULL ) - mailto = line->cl_file->cf_user; + /* determine which will be the mail receiver */ + if ( (mailto = line->cl_file->cf_mailto) == NULL ) + mailto = line->cl_file->cf_user; - /* change permissions */ - if (change_user(line->cl_file->cf_user, 1) < 0) - return ; - - /* run sendmail with mail file as standard input */ - execl(SENDMAIL, SENDMAIL, SENDMAIL_ARGS, mailto, NULL); - die_e("Can't exec " SENDMAIL); - break; - - case -1: - error_e("Could not exec '%s'", line->cl_shell); - break; + /* run sendmail with mail file as standard input */ + execl(SENDMAIL, SENDMAIL, SENDMAIL_ARGS, mailto, NULL); + die_e("Can't exec " SENDMAIL); - default: - /* parent */ - - } -} - -void -end_mailer(CL *line, int status) - /* take care of a finished mailer */ -{ -//////// - debug(" end mailer"); -//////// - - if (WIFEXITED(status) && WEXITSTATUS(status)!=0) - error("Tried to mail output of job `%s', " - "but mailer process (" SENDMAIL ") exited with status %d", - line->cl_shell, WEXITSTATUS(status) ); - else if (!WIFEXITED(status) && WIFSIGNALED(status)) - error("Tried to mail output of job `%s', " - "but mailer process (" SENDMAIL ") got signal %d", - line->cl_shell, WTERMSIG(status) ); - else if (!WIFEXITED(status) && !WIFSIGNALED(status)) - error("Tried to mail output of job `%s', " - "but mailer process (" SENDMAIL ") terminated abnormally" - , line->cl_shell); - - line->cl_mailpid = 0; } - int temp_file(void) /* Open a temporary file and return its file descriptor */