240
266
if (read_proc(&prcs_run, &prcs_blked))
243
newpar = (par*numcpu) - prcs_run + 1; /* +1 for startpar its self */
244
newpar -= (prcs_blked * iorate); /* I/O load reduction */
269
/* if we have preload running, we expect I/O not to be a problem */
270
if (ispreload != NoPreload)
273
newpar = (par*numcpu) - prcs_run + 1; /* +1 for startpar its self */
274
newpar -= (int)(((double)prcs_blked)*iorate); /* I/O load reduction */
247
fprintf(stderr, "checksystem par=%d newpar=%d (prcs_run=%u) %ld\n", par, newpar, prcs_run, time(0));
277
fprintf(stderr, "checksystem par=%d newpar=%d (prcs_run=%lu) %ld\n", par, newpar, prcs_run, time(0));
256
static inline int checklimit(const int par, const char *mode)
258
return checksystem(par, mode, true);
261
static inline int checkpar(const int par, const char *mode)
263
return checksystem(par, mode, false);
286
static inline int checklimit(const int par, const boolean start)
288
return checksystem(par, start, true);
291
static inline int checkpar(const int par, const boolean start)
293
return checksystem(par, start, false);
296
#define SOCK_PATH "/dev/shm/preload_sock"
266
298
void run(struct prg *p)
301
pid_t parent = getpid();
271
304
p->pid = (pid_t)0;
301
334
(void)signal(SIGQUIT, SIG_DFL);
302
335
(void)signal(SIGSEGV, SIG_DFL);
303
336
(void)signal(SIGTERM, SIG_DFL);
337
(void)signal(SIGCHLD, SIG_DFL);
305
339
if (setpgid(0, 0))
306
340
perror("setpgid");
344
while (close(1) < 0 && (errno == EINTR))
311
346
if (open(m, O_RDWR) != 1)
351
while (dup2(1, 2) < 0 && (errno == EINTR))
318
353
tio.c_oflag &= ~OPOST;
319
354
if (tcsetattr(1, TCSANOW, &tio))
320
355
perror("tcsetattr");
321
if (wzok && ioctl(0, TIOCSWINSZ, &wz))
322
perror("TIOCSWINSZ");
357
ioctl(1, TIOCSWINSZ, &wz);
363
while (dup2(2, 1) < 0 && (errno == EINTR))
334
snprintf(path, sizeof(path), INITDDIR "/%s", p->name);
335
execlp(path, path, arg, (char *)0);
337
execlp(p->name, p->name, arg, (char *)0);
369
if (!strcmp(arg, "start"))
373
struct sockaddr_un remote;
376
s = socket(AF_UNIX, SOCK_STREAM, 0);
379
memset(&remote, 0, sizeof(struct sockaddr_un));
380
remote.sun_family = AF_UNIX;
381
strcpy(remote.sun_path, SOCK_PATH);
382
len = strlen(remote.sun_path) + sizeof(remote.sun_family);
384
t = connect(s, (struct sockaddr *)&remote, len);
387
if (ispreload != Preload)
388
kill(parent, SIGUSR1);
389
send(s, p->name, strlen(p->name), 0);
390
recv(s, str, 100, 0);
392
else if ( ispreload == Unknown)
395
* if we connected to preload once, we know it ran.
396
* In case we can't connect to it later, it means it did
397
* its job and we can guess I/O is no longer a problem.
399
kill(parent, SIGUSR2);
403
* if we use preload, we fork again to make bootcharts easier to read.
404
* The reason is that the name of the init script will otherwise be used
405
* when in reality the above code waited for preload. If we fork away
406
* before the exec, the waiting code will be folded into startpar
411
int ret = waitpid(child, &status, 0);
414
exit(WEXITSTATUS(status));
422
snprintf(path, sizeof(path), "/etc/init.d/%s", p->name);
423
execlp(path, p->arg0, arg, (char *)0);
426
execlp(p->name, p->arg0, arg, (char *)0);
339
execlp(p->name, p->name, (char *)0);
428
execlp(p->name, p->arg0, (char *)0);
344
int run_single(char *prg, int spl)
433
int run_single(const char *prg, const char *arg0, int spl)
359
448
(void)signal(SIGQUIT, SIG_DFL);
360
449
(void)signal(SIGSEGV, SIG_DFL);
361
450
(void)signal(SIGTERM, SIG_DFL);
451
(void)signal(SIGCHLD, SIG_DFL);
453
while (dup2(2, 1) < 0 && (errno == EINTR))
369
snprintf(path, sizeof(path), INITDDIR "/%s", prg);
370
execlp(path, path, arg, (char *)0);
459
snprintf(path, sizeof(path), "/etc/init.d/%s", prg);
460
execlp(path, arg0 ? arg0 : path, arg, (char *)0);
373
execlp(prg, prg, arg, (char *)0);
463
execlp(prg, arg0 ? arg0 : prg, arg, (char *)0);
375
execlp(prg, prg, (char *)0);
465
execlp(prg, arg0 ? arg0 : prg, (char *)0);
380
while (waitpid(pid, &r, 0) == (pid_t)-1)
470
while ((waitpid(pid, &r, 0) == (pid_t)-1) && (errno == EINTR))
382
472
callsplash(spl, prg, arg);
383
473
return WIFEXITED(r) ? WEXITSTATUS(r) : (WIFSIGNALED(r) ? 1 : 255);
493
void sigchld(int sig __attribute__ ((unused)))
582
static void sigchld(int sig __attribute__ ((unused)))
496
585
write(pidpipe[1], &c, 1);
588
static void sigwinch(int sig __attribute__ ((unused)))
590
if (ioctl(0, TIOCGWINSZ, &wz) < 0)
595
if (wz.ws_row == 0) wz.ws_row = 24;
596
if (wz.ws_col == 0) wz.ws_col = 80;
597
snprintf(sz.env_row, sizeof(sz.env_row), "LINES=%d", wz.ws_row);
598
snprintf(sz.env_col, sizeof(sz.env_col), "COLUMNS=%d", wz.ws_col);
499
601
void usage(int status)
501
603
fprintf(stderr, "usage: startpar [options] [-a arg] prgs\n");
514
616
int main(int argc, char **argv)
519
int r, c, i, s, last, num;
523
626
struct timeval tv;
527
628
char pipebuf[16];
529
629
struct prg *gtimo_running = 0;
530
630
struct prg *interactive_task = NULL;
532
char *prev_level = NULL, *run_level = NULL;
631
char *prev_level = getenv("PREVLEVEL");
632
char *run_level = getenv("RUNLEVEL");
533
633
char *splashopt = 0;
635
(void)signal(SIGUSR1, sighandler_preload);
636
(void)signal(SIGUSR2, sighandler_nopreload);
638
(void)signal(SIGCHLD, SIG_DFL);
535
639
numcpu = sysconf(_SC_NPROCESSORS_ONLN);
536
640
myname = argv[0];
623
729
fprintf(stderr, "invalid run mode %s\n", run_mode);
626
snprintf(makefile, sizeof(makefile), INITDDIR "/.depend.%s", run_mode);
732
snprintf(makefile, sizeof(makefile), "/etc/init.d/.depend.%s", run_mode);
627
733
parse_makefile(makefile);
628
734
check_run_files(run_mode, prev_level, run_level);
630
736
argc = tree_entries; /* number of handled scripts */
737
isstart = !strcmp(arg, "start");
678
*nodevec = pickup_task();
680
*resvec = run_single((*nodevec)->name, calcsplash(0, 1, splashopt));
681
finish_task(*nodevec);
789
if ((*nodevec = pickup_task()))
791
*resvec = run_single((*nodevec)->name, (*nodevec)->arg0, calcsplash(0, 1, splashopt));
792
finish_task(*nodevec);
684
*resvec = run_single(*argv, calcsplash(0, 1, splashopt));
795
*resvec = run_single(*argv, *argv, calcsplash(0, 1, splashopt));
699
819
if (ioctl(0, TIOCGWINSZ, &wz) == 0)
821
if (wz.ws_row == 0) wz.ws_row = 24;
822
if (wz.ws_col == 0) wz.ws_col = 80;
824
strcat(&sz.env_row[0], "LINES=");
825
strcat(&sz.env_col[0], "COLUMNS=");
826
snprintf(sz.env_row, sizeof(sz.env_row), "LINES=%d", wz.ws_row);
827
snprintf(sz.env_col, sizeof(sz.env_col), "COLUMNS=%d", wz.ws_col);
702
829
if (pipe(pidpipe))
718
broken = 0; /* Detect broken hardware */
719
845
gettimeofday(&glastio, 0);
720
limit = checklimit(inpar, (run_mode) ? run_mode : "stop");
721
lastlim.tv_sec = glastio.tv_sec;
722
lastlim.tv_usec = glastio.tv_usec;
846
limit = checklimit(inpar, isstart);
727
857
gettimeofday(&now, 0);
729
tv.tv_sec = now.tv_sec;
730
tv.tv_usec = now.tv_usec;
736
diff = ((now.tv_sec - lastlim.tv_sec) * 1000) +
737
((now.tv_usec - lastlim.tv_usec)/ 1000);
738
if (diff >= 300 || diff < 0)
861
if ((diff = timerdiff(now, lastlim)) >= 300 || diff < 0)
741
864
fprintf(stderr, "%d: doing checklimit after %ldms %ld\n", getpid(), diff, time(0));
743
limit = checklimit(inpar, (run_mode) ? run_mode : "stop");
866
if ((limit = checklimit(inpar, isstart)) > argc)
745
867
limit = argc; /* not more than the number of all scripts */
746
lastlim.tv_sec = now.tv_sec;
747
lastlim.tv_usec = now.tv_usec;
751
fprintf(stderr, "par = %d, inpar = %d, limit = %d (diff=%ld)\n", par, inpar, limit, diff);
872
fprintf(stderr, "par=%d, inpar=%d, limit=%d (diff=%ld)\n", par, inpar, limit, diff);
753
for (s = 0; s < par; s++)
874
for (s = 0; s < par; s++) /* never leave this with break!! */
876
account: /* for the new process below */
756
878
if (p == interactive_task)
757
continue; /* don't handle this here */
879
continue; /* don't count this here */
758
880
if (p->fd || p->pid)
759
881
active++; /* count all running procs */
762
if (p->pid == 0 && num < argc && !interactive_task)
884
if (interactive_task)
885
continue; /* dont't start new processes */
887
continue; /* nothing to do */
764
890
if (active >= limit)
765
break; /* load balancing */
891
continue; /* load balancing */
768
nodevec[num] = pickup_task();
894
if ((nodevec[num] = pickup_task()) == NULL)
771
896
if (nodevec[num]->interactive)
772
897
interactive_task = p;
773
898
p->name = nodevec[num]->name;
899
p->arg0 = nodevec[num]->arg0 ? nodevec[num]->arg0 : nodevec[num]->name;
776
902
p->name = *argv++;
777
905
p->splashadd = calcsplash(num, argc, splashopt);
779
907
if (interactive_task)
908
continue; /* don't start this here */
782
active++; /* remember this _new_ proc!!! */
785
912
resvec[p->num] = 1;
787
914
finish_task(nodevec[p->num]);
788
active--; /* fork in run() failed, sigh! */
916
gettimeofday(&now, 0);
918
goto account; /* take the new process into account */
799
if ((last < 0) || (tv.tv_sec > p->lastio.tv_sec) ||
800
(tv.tv_sec == p->lastio.tv_sec && tv.tv_usec > p->lastio.tv_usec))
927
if ((last < 0) || timercmp(&tv,&p->lastio,>))
803
tv.tv_sec = p->lastio.tv_sec;
804
tv.tv_usec = p->lastio.tv_usec;
807
932
} /* for (s = 0; s < par; s++) */
809
broken++; /* no endless loops due broken systems */
811
934
if (interactive_task)
815
938
p = interactive_task;
816
resvec[p->num] = run_single(p->name, p->splashadd);
939
resvec[p->num] = run_single(p->name, p->arg0, p->splashadd);
818
941
finish_task(nodevec[p->num]);
821
944
interactive_task = NULL;
822
broken = 0; /* run_single() uses waitpid() */
827
if ((active < limit) && (num < argc) && (broken < argc))
828
continue; /* try to start new processes */
833
952
fprintf(stderr, "ERROR: not all processed (%d of %d)\n", num, argc);
835
if ((pid = waitpid(-1, &r, maxfd < 0 ? 0 : WNOHANG)) > 0)
954
if ((pid = waitpid(-1, &r, (maxfd < 0 ? 0 : WNOHANG)|WUNTRACED)) > 0)
836
955
fprintf(stderr, "ERROR: not all processes are checked\n");
841
960
fprintf(stderr, "active = %d\n", active);
843
962
if (active == 1 && last >= 0)
846
if ((pid = waitpid(p->pid, &r, maxfd < 0 ? 0 : WNOHANG)) == 0)
965
if ((pid = waitpid(p->pid, &r, (maxfd < 0 ? 0 : WNOHANG)|WUNTRACED)) == 0)
854
972
FD_SET(pidpipe[0], &rset);