[BACK]Return to job.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / make

Annotation of src/usr.bin/make/job.c, Revision 1.146

1.145     espie       1: /*     $OpenBSD: job.c,v 1.144 2019/12/31 13:59:14 espie Exp $ */
1.6       millert     2: /*     $NetBSD: job.c,v 1.16 1996/11/06 17:59:08 christos Exp $        */
1.1       deraadt     3:
                      4: /*
1.124     espie       5:  * Copyright (c) 2012 Marc Espie.
                      6:  *
                      7:  * Extensive code modifications for the OpenBSD project.
                      8:  *
                      9:  * Redistribution and use in source and binary forms, with or without
                     10:  * modification, are permitted provided that the following conditions
                     11:  * are met:
                     12:  * 1. Redistributions of source code must retain the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer.
                     14:  * 2. Redistributions in binary form must reproduce the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer in the
                     16:  *    documentation and/or other materials provided with the distribution.
                     17:  *
                     18:  * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT AND CONTRIBUTORS
                     19:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
                     20:  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
                     21:  * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OPENBSD
                     22:  * PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
                     23:  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
                     24:  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     25:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     26:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     27:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
                     28:  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     29:  */
                     30: /*
1.1       deraadt    31:  * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
                     32:  * Copyright (c) 1988, 1989 by Adam de Boor
                     33:  * Copyright (c) 1989 by Berkeley Softworks
                     34:  * All rights reserved.
                     35:  *
                     36:  * This code is derived from software contributed to Berkeley by
                     37:  * Adam de Boor.
                     38:  *
                     39:  * Redistribution and use in source and binary forms, with or without
                     40:  * modification, are permitted provided that the following conditions
                     41:  * are met:
                     42:  * 1. Redistributions of source code must retain the above copyright
                     43:  *    notice, this list of conditions and the following disclaimer.
                     44:  * 2. Redistributions in binary form must reproduce the above copyright
                     45:  *    notice, this list of conditions and the following disclaimer in the
                     46:  *    documentation and/or other materials provided with the distribution.
1.55      millert    47:  * 3. Neither the name of the University nor the names of its contributors
1.1       deraadt    48:  *    may be used to endorse or promote products derived from this software
                     49:  *    without specific prior written permission.
                     50:  *
                     51:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     52:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     53:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     54:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     55:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     56:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     57:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     58:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     59:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     60:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     61:  * SUCH DAMAGE.
                     62:  */
                     63:
                     64: /*-
                     65:  * job.c --
                     66:  *     handle the creation etc. of our child processes.
                     67:  *
                     68:  * Interface:
1.40      espie      69:  *     Job_Make                Start the creation of the given target.
1.1       deraadt    70:  *
1.124     espie      71:  *     Job_Init                Called to initialize this module.
                     72:  *
                     73:  *     Job_Begin               execute commands attached to the .BEGIN target
                     74:  *                             if any.
1.40      espie      75:  *
1.117     espie      76:  *     can_start_job           Return true if we can start job
1.40      espie      77:  *
1.41      espie      78:  *     Job_Empty               Return true if the job table is completely
1.40      espie      79:  *                             empty.
                     80:  *
                     81:  *     Job_Finish              Perform any final processing which needs doing.
                     82:  *                             This includes the execution of any commands
                     83:  *                             which have been/were attached to the .END
1.124     espie      84:  *                             target.
1.40      espie      85:  *
1.117     espie      86:  *     Job_AbortAll            Abort all current jobs. It doesn't
1.40      espie      87:  *                             handle output or do anything for the jobs,
1.124     espie      88:  *                             just kills them.
1.1       deraadt    89:  *
1.117     espie      90:  *     Job_Wait                Wait for all running jobs to finish.
1.1       deraadt    91:  */
                     92:
                     93: #include <sys/types.h>
                     94: #include <sys/wait.h>
1.41      espie      95: #include <ctype.h>
                     96: #include <errno.h>
1.1       deraadt    97: #include <fcntl.h>
1.41      espie      98: #include <signal.h>
1.69      espie      99: #include <stdarg.h>
1.1       deraadt   100: #include <stdio.h>
1.42      espie     101: #include <stdlib.h>
1.1       deraadt   102: #include <string.h>
1.41      espie     103: #include <unistd.h>
                    104: #include "config.h"
                    105: #include "defines.h"
1.1       deraadt   106: #include "job.h"
1.63      espie     107: #include "engine.h"
1.1       deraadt   108: #include "pathnames.h"
1.41      espie     109: #include "var.h"
                    110: #include "targ.h"
                    111: #include "error.h"
1.124     espie     112: #include "extern.h"
1.41      espie     113: #include "lst.h"
                    114: #include "gnode.h"
                    115: #include "memory.h"
                    116: #include "make.h"
1.124     espie     117: #include "buf.h"
1.78      espie     118:
1.40      espie     119: static int     aborting = 0;       /* why is the make aborting? */
                    120: #define ABORT_ERROR    1           /* Because of an error */
                    121: #define ABORT_INTERRUPT 2          /* Because it was interrupted */
                    122: #define ABORT_WAIT     3           /* Waiting for jobs to finish */
1.1       deraadt   123:
1.40      espie     124: static int     maxJobs;        /* The most children we can run at once */
1.124     espie     125: static int     nJobs;          /* Number of jobs already allocated */
                    126: static bool    no_new_jobs;    /* Mark recursive shit so we shouldn't start
                    127:                                 * something else at the same time
                    128:                                 */
                    129: Job *runningJobs;              /* Jobs currently running a process */
                    130: Job *errorJobs;                        /* Jobs in error at end */
                    131: static Job *heldJobs;          /* Jobs not running yet because of expensive */
1.134     espie     132: static pid_t mypid;            /* Used for printing debugging messages */
1.1       deraadt   133:
1.128     espie     134: static volatile sig_atomic_t got_fatal;
1.112     espie     135:
1.124     espie     136: static volatile sig_atomic_t got_SIGINT, got_SIGHUP, got_SIGQUIT, got_SIGTERM,
1.128     espie     137:     got_SIGINFO;
1.112     espie     138:
1.124     espie     139: static sigset_t sigset, emptyset;
1.112     espie     140:
1.126     espie     141: static void handle_fatal_signal(int);
1.124     espie     142: static void handle_siginfo(void);
1.142     espie     143: static void postprocess_job(Job *);
1.124     espie     144: static Job *prepare_job(GNode *);
                    145: static void determine_job_next_step(Job *);
1.142     espie     146: static void remove_job(Job *);
1.124     espie     147: static void may_continue_job(Job *);
                    148: static void continue_job(Job *);
                    149: static Job *reap_finished_job(pid_t);
                    150: static bool reap_jobs(void);
1.146   ! espie     151: static void may_continue_heldback_jobs();
1.112     espie     152:
1.111     espie     153: static void loop_handle_running_jobs(void);
1.124     espie     154: static bool expensive_job(Job *);
                    155: static bool expensive_command(const char *);
                    156: static void setup_signal(int);
                    157: static void notice_signal(int);
                    158: static void setup_all_signals(void);
1.128     espie     159: static const char *really_kill(Job *, int);
                    160: static void debug_kill_printf(const char *, ...);
                    161: static void debug_vprintf(const char *, va_list);
                    162: static void may_remove_target(Job *);
1.131     espie     163: static void print_error(Job *);
                    164: static void internal_print_errors(void);
                    165:
                    166: static int dying_signal = 0;
                    167:
                    168: const char *   basedirectory = NULL;
1.127     espie     169:
1.128     espie     170: static const char *
                    171: really_kill(Job *job, int signo)
                    172: {
                    173:        pid_t pid = job->pid;
                    174:        if (getpgid(pid) != getpgrp()) {
                    175:                if (killpg(pid, signo) == 0)
                    176:                        return "group got signal";
                    177:                pid = -pid;
                    178:        } else {
                    179:                if (kill(pid, signo) == 0)
                    180:                        return "process got signal";
                    181:        }
1.138     natano    182:        if (errno == ESRCH)
1.128     espie     183:                job->flags |= JOB_LOST;
1.138     natano    184:        return strerror(errno);
1.128     espie     185: }
                    186:
                    187: static void
                    188: may_remove_target(Job *j)
                    189: {
1.131     espie     190:        int dying = check_dying_signal();
                    191:
                    192:        if (dying && !noExecute && !Targ_Precious(j->node)) {
1.128     espie     193:                const char *file = Var(TARGET_INDEX, j->node);
                    194:                int r = eunlink(file);
                    195:
                    196:                if (DEBUG(JOB) && r == -1)
                    197:                        fprintf(stderr, " *** would unlink %s\n", file);
                    198:                if (r != -1)
                    199:                        fprintf(stderr, " *** %s removed\n", file);
1.127     espie     200:        }
                    201: }
1.126     espie     202:
1.131     espie     203: static void
                    204: buf_addcurdir(BUFFER *buf)
                    205: {
                    206:        const char *v = Var_Value(".CURDIR");
                    207:        if (basedirectory != NULL) {
                    208:                size_t len = strlen(basedirectory);
                    209:                if (strncmp(basedirectory, v, len) == 0 &&
                    210:                    v[len] == '/') {
                    211:                        v += len+1;
                    212:                } else if (strcmp(basedirectory, v) == 0) {
                    213:                        Buf_AddString(buf, ".");
                    214:                        return;
                    215:                }
                    216:        }
                    217:        Buf_AddString(buf, v);
                    218: }
                    219:
                    220: static const char *
                    221: shortened_curdir(void)
                    222: {
                    223:        static BUFFER buf;
1.140     espie     224:        static bool first = true;
1.131     espie     225:        if (first) {
                    226:                Buf_Init(&buf, 0);
                    227:                buf_addcurdir(&buf);
                    228:                first = false;
                    229:        }
                    230:        return Buf_Retrieve(&buf);
                    231: }
                    232:
                    233: static void
                    234: quick_error(Job *j, int signo, bool first)
                    235: {
                    236:        if (first) {
                    237:                fprintf(stderr, "*** Signal SIG%s", sys_signame[signo]);
                    238:                fprintf(stderr, " in %s (", shortened_curdir());
                    239:        } else
                    240:                fprintf(stderr, " ");
                    241:
                    242:        fprintf(stderr, "%s", j->node->name);
                    243:        free(j->cmd);
                    244: }
                    245:
1.126     espie     246: static void
1.130     espie     247: print_error(Job *j)
1.126     espie     248: {
1.130     espie     249:        static bool first = true;
1.131     espie     250:        BUFFER buf;
                    251:
                    252:        Buf_Init(&buf, 0);
1.126     espie     253:
1.131     espie     254:        if (j->exit_type == JOB_EXIT_BAD)
                    255:                Buf_printf(&buf, "*** Error %d", j->code);
                    256:        else if (j->exit_type == JOB_SIGNALED) {
1.128     espie     257:                if (j->code < NSIG)
1.131     espie     258:                        Buf_printf(&buf, "*** Signal SIG%s",
1.128     espie     259:                            sys_signame[j->code]);
                    260:                else
1.131     espie     261:                        Buf_printf(&buf, "*** unknown signal %d", j->code);
1.128     espie     262:        } else
1.131     espie     263:                Buf_printf(&buf, "*** Should not happen %d/%d",
                    264:                    j->exit_type, j->code);
1.128     espie     265:        if (DEBUG(KILL) && (j->flags & JOB_LOST))
1.131     espie     266:                Buf_AddChar(&buf, '!');
1.130     espie     267:        if (first) {
1.131     espie     268:                Buf_AddString(&buf, " in ");
                    269:                buf_addcurdir(&buf);
1.130     espie     270:                first = false;
                    271:        }
1.131     espie     272:        Buf_printf(&buf, " (%s:%lu", j->location->fname, j->location->lineno);
                    273:        Buf_printf(&buf, " '%s'", j->node->name);
                    274:        if ((j->flags & (JOB_SILENT | JOB_IS_EXPENSIVE)) == JOB_SILENT
1.132     espie     275:            && Buf_Size(&buf) < 140-2) {
1.131     espie     276:                size_t len = strlen(j->cmd);
                    277:                Buf_AddString(&buf, ": ");
                    278:                if (len + Buf_Size(&buf) < 140)
                    279:                        Buf_AddString(&buf, j->cmd);
                    280:                else {
                    281:                        Buf_AddChars(&buf, 140 - Buf_Size(&buf), j->cmd);
                    282:                        Buf_AddString(&buf, "...");
                    283:                }
                    284:        }
                    285:        fprintf(stderr, "%s)\n", Buf_Retrieve(&buf));
                    286:        Buf_Destroy(&buf);
1.126     espie     287:        free(j->cmd);
1.131     espie     288: }
                    289: static void
                    290: quick_summary(int signo)
                    291: {
                    292:        Job *j, *k, *jnext;
                    293:        bool first = true;
                    294:
                    295:        k = errorJobs;
                    296:        errorJobs = NULL;
                    297:        for (j = k; j != NULL; j = jnext) {
                    298:                jnext = j->next;
                    299:                if ((j->exit_type == JOB_EXIT_BAD && j->code == signo+128) ||
                    300:                    (j->exit_type == JOB_SIGNALED && j->code == signo)) {
                    301:                        quick_error(j, signo, first);
                    302:                        first = false;
                    303:                } else {
                    304:                        j->next = errorJobs;
                    305:                        errorJobs = j;
                    306:                }
                    307:        }
                    308:        if (!first)
                    309:                fprintf(stderr, ")\n");
1.126     espie     310: }
1.93      espie     311:
1.131     espie     312: static void
                    313: internal_print_errors()
1.101     espie     314: {
1.126     espie     315:        Job *j, *k, *jnext;
1.131     espie     316:        int dying;
1.124     espie     317:
1.130     espie     318:        if (!errorJobs)
1.133     espie     319:                fprintf(stderr, "Stop in %s\n", shortened_curdir());
1.1       deraadt   320:
1.131     espie     321:        for (j = errorJobs; j != NULL; j = j->next)
                    322:                may_remove_target(j);
                    323:        dying = check_dying_signal();
                    324:        if (dying)
                    325:                quick_summary(dying);
1.143     espie     326:        /* Print errors grouped by file name. */
1.126     espie     327:        while (errorJobs != NULL) {
1.143     espie     328:                /* Select the first job. */
1.126     espie     329:                k = errorJobs;
                    330:                errorJobs = NULL;
                    331:                for (j = k; j != NULL; j = jnext) {
                    332:                        jnext = j->next;
                    333:                        if (j->location->fname == k->location->fname)
1.143     espie     334:                                /* Print errors with the same filename. */
1.130     espie     335:                                print_error(j);
1.126     espie     336:                        else {
1.143     espie     337:                                /* Keep others for the next iteration. */
1.126     espie     338:                                j->next = errorJobs;
                    339:                                errorJobs = j;
                    340:                        }
                    341:                }
1.101     espie     342:        }
1.88      espie     343: }
                    344:
1.131     espie     345: void
                    346: print_errors(void)
                    347: {
                    348:        handle_all_signals();
                    349:        internal_print_errors();
                    350: }
                    351:
1.57      espie     352: static void
1.124     espie     353: setup_signal(int sig)
1.57      espie     354: {
1.124     espie     355:        if (signal(sig, SIG_IGN) != SIG_IGN) {
                    356:                (void)signal(sig, notice_signal);
                    357:                sigaddset(&sigset, sig);
1.57      espie     358:        }
                    359: }
                    360:
                    361: static void
1.124     espie     362: notice_signal(int sig)
1.1       deraadt   363: {
1.126     espie     364:
1.124     espie     365:        switch(sig) {
1.117     espie     366:        case SIGINT:
                    367:                got_SIGINT++;
1.124     espie     368:                got_fatal = 1;
                    369:                break;
1.117     espie     370:        case SIGHUP:
                    371:                got_SIGHUP++;
1.124     espie     372:                got_fatal = 1;
                    373:                break;
1.117     espie     374:        case SIGQUIT:
                    375:                got_SIGQUIT++;
1.124     espie     376:                got_fatal = 1;
                    377:                break;
1.117     espie     378:        case SIGTERM:
                    379:                got_SIGTERM++;
1.124     espie     380:                got_fatal = 1;
1.117     espie     381:                break;
1.124     espie     382:        case SIGINFO:
                    383:                got_SIGINFO++;
1.117     espie     384:                break;
1.124     espie     385:        case SIGCHLD:
1.117     espie     386:                break;
1.66      espie     387:        }
1.124     espie     388: }
1.117     espie     389:
1.135     espie     390: static void
1.124     espie     391: setup_all_signals(void)
                    392: {
                    393:        sigemptyset(&sigset);
                    394:        sigemptyset(&emptyset);
                    395:        /*
                    396:         * Catch the four signals that POSIX specifies if they aren't ignored.
                    397:         * handle_signal will take care of calling JobInterrupt if appropriate.
                    398:         */
                    399:        setup_signal(SIGINT);
                    400:        setup_signal(SIGHUP);
                    401:        setup_signal(SIGQUIT);
                    402:        setup_signal(SIGTERM);
                    403:        /* Display running jobs on SIGINFO */
                    404:        setup_signal(SIGINFO);
                    405:        /* Have to see SIGCHLD */
                    406:        setup_signal(SIGCHLD);
                    407:        got_fatal = 0;
1.1       deraadt   408: }
                    409:
1.124     espie     410: static void
                    411: handle_siginfo(void)
1.1       deraadt   412: {
1.126     espie     413:        static BUFFER buf;
                    414:        static size_t length = 0;
                    415:
1.124     espie     416:        Job *job;
                    417:        bool first = true;
1.66      espie     418:
1.124     espie     419:        got_SIGINFO = 0;
                    420:        /* we have to store the info in a buffer, because status from all
                    421:         * makes running would get intermixed otherwise
1.66      espie     422:         */
1.124     espie     423:
1.126     espie     424:        if (length == 0) {
                    425:                Buf_Init(&buf, 0);
1.131     espie     426:                Buf_printf(&buf, "%s in ", Var_Value("MAKE"));
                    427:                buf_addcurdir(&buf);
                    428:                Buf_AddString(&buf, ": ");
1.126     espie     429:                length = Buf_Size(&buf);
                    430:        } else
                    431:                Buf_Truncate(&buf, length);
1.124     espie     432:
                    433:        for (job = runningJobs; job != NULL ; job = job->next) {
                    434:                if (!first)
                    435:                        Buf_puts(&buf, ", ");
                    436:                first = false;
                    437:                Buf_puts(&buf, job->node->name);
                    438:        }
                    439:        Buf_puts(&buf, first ? "nothing running\n" : "\n");
1.1       deraadt   440:
1.124     espie     441:        fputs(Buf_Retrieve(&buf), stderr);
1.1       deraadt   442: }
                    443:
1.131     espie     444: int
                    445: check_dying_signal(void)
                    446: {
                    447:        sigset_t set;
                    448:        if (dying_signal)
                    449:                return dying_signal;
                    450:        sigpending(&set);
                    451:        if (got_SIGINT || sigismember(&set, SIGINT))
                    452:                return dying_signal = SIGINT;
                    453:        if (got_SIGHUP || sigismember(&set, SIGHUP))
                    454:                return dying_signal = SIGHUP;
                    455:        if (got_SIGQUIT || sigismember(&set, SIGQUIT))
                    456:                return dying_signal = SIGQUIT;
                    457:        if (got_SIGTERM || sigismember(&set, SIGTERM))
                    458:                return dying_signal = SIGTERM;
                    459:        return 0;
                    460: }
                    461:
1.124     espie     462: void
                    463: handle_all_signals(void)
1.1       deraadt   464: {
1.124     espie     465:        if (got_SIGINFO)
                    466:                handle_siginfo();
                    467:        while (got_fatal) {
                    468:                got_fatal = 0;
                    469:                aborting = ABORT_INTERRUPT;
                    470:
                    471:                if (got_SIGINT) {
                    472:                        got_SIGINT=0;
1.126     espie     473:                        handle_fatal_signal(SIGINT);
1.124     espie     474:                }
                    475:                if (got_SIGHUP) {
                    476:                        got_SIGHUP=0;
1.126     espie     477:                        handle_fatal_signal(SIGHUP);
1.124     espie     478:                }
                    479:                if (got_SIGQUIT) {
                    480:                        got_SIGQUIT=0;
1.126     espie     481:                        handle_fatal_signal(SIGQUIT);
1.124     espie     482:                }
                    483:                if (got_SIGTERM) {
                    484:                        got_SIGTERM=0;
1.126     espie     485:                        handle_fatal_signal(SIGTERM);
1.124     espie     486:                }
                    487:        }
1.1       deraadt   488: }
                    489:
1.128     espie     490: static void
                    491: debug_vprintf(const char *fmt, va_list va)
                    492: {
                    493:        (void)printf("[%ld] ", (long)mypid);
                    494:        (void)vprintf(fmt, va);
                    495:        fflush(stdout);
                    496: }
                    497:
1.124     espie     498: void
                    499: debug_job_printf(const char *fmt, ...)
1.84      espie     500: {
                    501:        if (DEBUG(JOB)) {
                    502:                va_list va;
                    503:                va_start(va, fmt);
1.128     espie     504:                debug_vprintf(fmt, va);
                    505:                va_end(va);
                    506:        }
                    507: }
                    508:
                    509: static void
                    510: debug_kill_printf(const char *fmt, ...)
                    511: {
                    512:        if (DEBUG(KILL)) {
                    513:                va_list va;
                    514:                va_start(va, fmt);
                    515:                debug_vprintf(fmt, va);
1.84      espie     516:                va_end(va);
                    517:        }
                    518: }
1.119     espie     519:
1.1       deraadt   520: /*-
                    521:  *-----------------------------------------------------------------------
1.124     espie     522:  * postprocess_job  --
                    523:  *     Do final processing for the given job including updating
1.119     espie     524:  *     parents and starting new jobs as available/necessary.
1.1       deraadt   525:  *
                    526:  * Side Effects:
1.6       millert   527:  *     If we got an error and are aborting (aborting == ABORT_ERROR) and
1.1       deraadt   528:  *     the job list is now empty, we are done for the day.
1.101     espie     529:  *     If we recognized an error we set the aborting flag
1.1       deraadt   530:  *     to ABORT_ERROR so no more jobs will be started.
                    531:  *-----------------------------------------------------------------------
                    532:  */
                    533: /*ARGSUSED*/
1.112     espie     534:
1.1       deraadt   535: static void
1.142     espie     536: postprocess_job(Job *job)
1.2       deraadt   537: {
1.142     espie     538:        if (job->exit_type == JOB_EXIT_OKAY &&
1.66      espie     539:            aborting != ABORT_ERROR &&
1.124     espie     540:            aborting != ABORT_INTERRUPT) {
1.66      espie     541:                /* As long as we aren't aborting and the job didn't return a
                    542:                 * non-zero status that we shouldn't ignore, we call
1.101     espie     543:                 * Make_Update to update the parents. */
1.141     espie     544:                job->node->built_status = REBUILT;
1.66      espie     545:                Make_Update(job->node);
1.124     espie     546:                free(job);
1.144     espie     547:        } else if (job->exit_type != JOB_EXIT_OKAY && keepgoing)
                    548:                free(job);
1.1       deraadt   549:
1.145     espie     550:        if (errorJobs != NULL && aborting != ABORT_INTERRUPT)
1.66      espie     551:                aborting = ABORT_ERROR;
1.6       millert   552:
1.124     espie     553:        if (aborting == ABORT_ERROR && DEBUG(QUICKDEATH))
1.126     espie     554:                handle_fatal_signal(SIGINT);
1.117     espie     555:        if (aborting == ABORT_ERROR && Job_Empty())
1.124     espie     556:                Finish();
1.1       deraadt   557: }
                    558:
1.124     espie     559: /* expensive jobs handling: in order to avoid forking an exponential number
                    560:  * of jobs, make tries to figure out "recursive make" configurations.
                    561:  * It may err on the side of caution.
                    562:  * Basically, a command is "expensive" if it's likely to fork an extra
                    563:  * level of make: either by looking at the command proper, or if it has
                    564:  * some specific qualities ('+cmd' are likely to be recursive, as are
                    565:  * .MAKE: commands).  It's possible to explicitly say some targets are
                    566:  * expensive or cheap with .EXPENSIVE or .CHEAP.
                    567:  *
                    568:  * While an expensive command is running, no_new_jobs
                    569:  * is set, so jobs that would fork new processes are accumulated in the
                    570:  * heldJobs list instead.
                    571:  *
                    572:  * This heuristics is also used on error exit: we display silent commands
                    573:  * that failed, unless those ARE expensive commands: expensive commands
                    574:  * are likely to not be failing by themselves, but to be the result of
                    575:  * a cascade of failures in descendant makes.
                    576:  */
                    577: void
                    578: determine_expensive_job(Job *job)
                    579: {
                    580:        if (expensive_job(job)) {
                    581:                job->flags |= JOB_IS_EXPENSIVE;
                    582:                no_new_jobs = true;
                    583:        } else
                    584:                job->flags &= ~JOB_IS_EXPENSIVE;
                    585:        if (DEBUG(EXPENSIVE))
                    586:                fprintf(stderr, "[%ld] Target %s running %.50s: %s\n",
                    587:                    (long)mypid, job->node->name, job->cmd,
                    588:                    job->flags & JOB_IS_EXPENSIVE ? "expensive" : "cheap");
1.101     espie     589: }
                    590:
1.124     espie     591: static bool
                    592: expensive_job(Job *job)
1.1       deraadt   593: {
1.124     espie     594:        if (job->node->type & OP_CHEAP)
                    595:                return false;
                    596:        if (job->node->type & (OP_EXPENSIVE | OP_MAKE))
                    597:                return true;
                    598:        return expensive_command(job->cmd);
1.96      espie     599: }
                    600:
1.117     espie     601: static bool
                    602: expensive_command(const char *s)
1.1       deraadt   603: {
1.117     espie     604:        const char *p;
                    605:        bool include = false;
                    606:        bool expensive = false;
1.66      espie     607:
1.117     espie     608:        /* okay, comments are cheap, always */
                    609:        if (*s == '#')
                    610:                return false;
1.124     espie     611:        /* and commands we always execute are expensive */
                    612:        if (*s == '+')
                    613:                return true;
1.66      espie     614:
1.117     espie     615:        for (p = s; *p != '\0'; p++) {
                    616:                if (*p == ' ' || *p == '\t') {
                    617:                        include = false;
                    618:                        if (p[1] == '-' && p[2] == 'I')
                    619:                                include = true;
                    620:                }
                    621:                if (include)
                    622:                        continue;
                    623:                /* KMP variant, avoid looking twice at the same
                    624:                 * letter.
                    625:                 */
                    626:                if (*p != 'm')
                    627:                        continue;
                    628:                if (p[1] != 'a')
                    629:                        continue;
                    630:                p++;
                    631:                if (p[1] != 'k')
                    632:                        continue;
                    633:                p++;
                    634:                if (p[1] != 'e')
                    635:                        continue;
                    636:                p++;
                    637:                expensive = true;
                    638:                while (p[1] != '\0' && p[1] != ' ' && p[1] != '\t') {
1.124     espie     639:                        if (p[1] == '.' || p[1] == '/') {
1.117     espie     640:                                expensive = false;
                    641:                                break;
1.66      espie     642:                        }
1.117     espie     643:                        p++;
1.1       deraadt   644:                }
1.117     espie     645:                if (expensive)
                    646:                        return true;
1.1       deraadt   647:        }
1.117     espie     648:        return false;
                    649: }
                    650:
1.98      espie     651: static Job *
1.124     espie     652: prepare_job(GNode *gn)
1.78      espie     653: {
1.124     espie     654:        /* a new job is prepared unless its commands are bogus (we don't
                    655:         * have anything for it), or if we're in touch mode.
                    656:         *
                    657:         * Note that even in noexec mode, some commands may still run
                    658:         * thanks to the +cmd construct.
1.1       deraadt   659:         */
1.124     espie     660:        if (node_find_valid_commands(gn)) {
                    661:                if (touchFlag) {
                    662:                        Job_Touch(gn);
                    663:                        return NULL;
                    664:                } else {
                    665:                        Job *job;
1.6       millert   666:
1.124     espie     667:                        job = emalloc(sizeof(Job));
                    668:                        if (job == NULL)
                    669:                                Punt("can't create job: out of memory");
1.66      espie     670:
1.124     espie     671:                        job_attach_node(job, gn);
                    672:                        return job;
                    673:                }
1.66      espie     674:        } else {
1.124     espie     675:                node_failure(gn);
                    676:                return NULL;
1.1       deraadt   677:        }
1.124     espie     678: }
1.66      espie     679:
1.124     espie     680: static void
                    681: may_continue_job(Job *job)
                    682: {
                    683:        if (no_new_jobs) {
                    684:                if (DEBUG(EXPENSIVE))
                    685:                        fprintf(stderr, "[%ld] expensive -> hold %s\n",
                    686:                            (long)mypid, job->node->name);
                    687:                job->next = heldJobs;
                    688:                heldJobs = job;
                    689:        } else
                    690:                continue_job(job);
                    691: }
1.122     espie     692:
1.124     espie     693: static void
                    694: continue_job(Job *job)
                    695: {
                    696:        bool finished = job_run_next(job);
                    697:        if (finished)
1.142     espie     698:                remove_job(job);
1.124     espie     699:        else
                    700:                determine_expensive_job(job);
1.98      espie     701: }
1.1       deraadt   702:
1.98      espie     703: /*-
                    704:  *-----------------------------------------------------------------------
1.124     espie     705:  * Job_Make  --
1.98      espie     706:  *     Start a target-creation process going for the target described
                    707:  *     by the graph node gn.
                    708:  *
                    709:  * Side Effects:
1.124     espie     710:  *     A new Job node is created and  its commands continued, which
                    711:  *     may fork the first command of that job.
1.98      espie     712:  *-----------------------------------------------------------------------
                    713:  */
1.124     espie     714: void
                    715: Job_Make(GNode *gn)
1.98      espie     716: {
                    717:        Job *job;
1.124     espie     718:
                    719:        job = prepare_job(gn);
1.98      espie     720:        if (!job)
                    721:                return;
1.124     espie     722:        nJobs++;
                    723:        may_continue_job(job);
1.1       deraadt   724: }
                    725:
1.101     espie     726: static void
1.124     espie     727: determine_job_next_step(Job *job)
1.2       deraadt   728: {
1.124     espie     729:        bool okay;
                    730:        if (job->flags & JOB_IS_EXPENSIVE) {
                    731:                no_new_jobs = false;
                    732:                if (DEBUG(EXPENSIVE))
                    733:                        fprintf(stderr, "[%ld] "
                    734:                            "Returning from expensive target %s, "
                    735:                            "allowing new jobs\n", (long)mypid,
                    736:                            job->node->name);
                    737:        }
1.2       deraadt   738:
1.142     espie     739:        if (job->exit_type != JOB_EXIT_OKAY || job->next_cmd == NULL)
                    740:                remove_job(job);
1.124     espie     741:        else
                    742:                may_continue_job(job);
1.101     espie     743: }
                    744:
                    745: static void
1.142     espie     746: remove_job(Job *job)
1.101     espie     747: {
1.124     espie     748:        nJobs--;
1.142     espie     749:        postprocess_job(job);
1.146   ! espie     750: }
        !           751:
        !           752: static void
        !           753: may_continue_heldback_jobs()
        !           754: {
1.124     espie     755:        while (!no_new_jobs) {
                    756:                if (heldJobs != NULL) {
1.146   ! espie     757:                        Job *job = heldJobs;
1.124     espie     758:                        heldJobs = heldJobs->next;
                    759:                        if (DEBUG(EXPENSIVE))
                    760:                                fprintf(stderr, "[%ld] cheap -> release %s\n",
                    761:                                    (long)mypid, job->node->name);
                    762:                        continue_job(job);
                    763:                } else
                    764:                        break;
1.2       deraadt   765:        }
                    766: }
1.111     espie     767:
1.124     espie     768: /*
                    769:  * job = reap_finished_job(pid):
                    770:  *     retrieve and remove a job from runningJobs, based on its pid
1.1       deraadt   771:  *
1.124     espie     772:  *     Note that we remove it right away, so that handle_signals()
                    773:  *     is accurate.
1.1       deraadt   774:  */
1.124     espie     775: static Job *
                    776: reap_finished_job(pid_t pid)
1.66      espie     777: {
1.124     espie     778:        Job **j, *job;
1.1       deraadt   779:
1.124     espie     780:        for (j = &runningJobs; *j != NULL; j = &((*j)->next))
                    781:                if ((*j)->pid == pid) {
                    782:                        job = *j;
                    783:                        *j = job->next;
                    784:                        return job;
1.66      espie     785:                }
1.1       deraadt   786:
1.124     espie     787:        return NULL;
1.101     espie     788: }
1.6       millert   789:
1.124     espie     790: /*
                    791:  * classic waitpid handler: retrieve as many dead children as possible.
                    792:  * returns true if succesful
                    793:  */
                    794: static bool
                    795: reap_jobs(void)
1.117     espie     796: {
1.124     espie     797:        pid_t pid;      /* pid of dead child */
                    798:        int status;     /* Exit/termination status */
                    799:        bool reaped = false;
1.117     espie     800:        Job *job;
                    801:
                    802:        while ((pid = waitpid(WAIT_ANY, &status, WNOHANG)) > 0) {
1.124     espie     803:                reaped = true;
                    804:                job = reap_finished_job(pid);
1.1       deraadt   805:
1.124     espie     806:                if (job == NULL) {
                    807:                        Punt("Child (%ld) not in table?", (long)pid);
1.66      espie     808:                } else {
1.124     espie     809:                        job_handle_status(job, status);
                    810:                        determine_job_next_step(job);
1.1       deraadt   811:                }
1.146   ! espie     812:                may_continue_heldback_jobs();
1.1       deraadt   813:        }
1.124     espie     814:        /* sanity check, should not happen */
                    815:        if (pid == -1 && errno == ECHILD && runningJobs != NULL)
                    816:                Punt("Process has no children, but runningJobs is not empty ?");
                    817:        return reaped;
1.1       deraadt   818: }
                    819:
                    820: void
1.124     espie     821: handle_running_jobs(void)
1.1       deraadt   822: {
1.124     espie     823:        sigset_t old;
                    824:        /* reaping children in the presence of caught signals */
1.91      espie     825:
1.124     espie     826:        /* first, we make sure to hold on new signals, to synchronize
                    827:         * reception of new stuff on sigsuspend
                    828:         */
                    829:        sigprocmask(SIG_BLOCK, &sigset, &old);
1.135     espie     830:        /* note this will NOT loop until runningJobs == NULL.
                    831:         * It's merely an optimisation, namely that we don't need to go
                    832:         * through the logic if no job is present. As soon as a job
                    833:         * gets reaped, we WILL exit the loop through the break.
                    834:         */
1.124     espie     835:        while (runningJobs != NULL) {
                    836:                /* did we already have pending stuff that advances things ?
                    837:                 * then handle_all_signals() will not return
                    838:                 * or reap_jobs() will reap_jobs()
                    839:                 */
                    840:                handle_all_signals();
                    841:                if (reap_jobs())
                    842:                        break;
                    843:                /* okay, so it's safe to suspend, we have nothing to do but
                    844:                 * wait...
                    845:                 */
                    846:                sigsuspend(&emptyset);
1.1       deraadt   847:        }
1.124     espie     848:        sigprocmask(SIG_SETMASK, &old, NULL);
1.1       deraadt   849: }
                    850:
1.111     espie     851: void
1.124     espie     852: handle_one_job(Job *job)
1.111     espie     853: {
1.124     espie     854:        int stat;
                    855:        int status;
                    856:        sigset_t old;
                    857:
                    858:        sigprocmask(SIG_BLOCK, &sigset, &old);
                    859:        while (1) {
                    860:                handle_all_signals();
                    861:                stat = waitpid(job->pid, &status, WNOHANG);
                    862:                if (stat == job->pid)
                    863:                        break;
                    864:                sigsuspend(&emptyset);
                    865:        }
                    866:        runningJobs = NULL;
                    867:        job_handle_status(job, status);
                    868:        sigprocmask(SIG_SETMASK, &old, NULL);
1.111     espie     869: }
                    870:
                    871: static void
                    872: loop_handle_running_jobs()
                    873: {
1.124     espie     874:        while (runningJobs != NULL)
1.111     espie     875:                handle_running_jobs();
                    876: }
1.1       deraadt   877:
                    878: void
1.83      espie     879: Job_Init(int maxproc)
1.1       deraadt   880: {
1.124     espie     881:        runningJobs = NULL;
                    882:        heldJobs = NULL;
                    883:        errorJobs = NULL;
1.117     espie     884:        maxJobs = maxproc;
1.124     espie     885:        mypid = getpid();
                    886:
1.117     espie     887:        nJobs = 0;
1.66      espie     888:
1.117     espie     889:        aborting = 0;
1.124     espie     890:        setup_all_signals();
1.1       deraadt   891: }
                    892:
1.41      espie     893: bool
1.117     espie     894: can_start_job(void)
1.1       deraadt   895: {
1.124     espie     896:        if (aborting || nJobs >= maxJobs)
1.117     espie     897:                return false;
1.119     espie     898:        else
1.117     espie     899:                return true;
1.1       deraadt   900: }
                    901:
1.41      espie     902: bool
1.56      espie     903: Job_Empty(void)
1.1       deraadt   904: {
1.124     espie     905:        return runningJobs == NULL;
1.1       deraadt   906: }
                    907:
                    908: /*-
                    909:  *-----------------------------------------------------------------------
1.126     espie     910:  * handle_fatal_signal --
                    911:  *     Handle the receipt of a fatal interrupt
1.1       deraadt   912:  *
                    913:  * Side Effects:
1.126     espie     914:  *     All children are killed. Another job may be started if there
                    915:  *     is an interrupt target and the signal was SIGINT.
1.1       deraadt   916:  *-----------------------------------------------------------------------
                    917:  */
                    918: static void
1.126     espie     919: handle_fatal_signal(int signo)
1.1       deraadt   920: {
1.124     espie     921:        Job *job;
1.66      espie     922:
1.128     espie     923:        debug_kill_printf("handle_fatal_signal(%d) called.\n", signo);
1.66      espie     924:
1.131     espie     925:        dying_signal = signo;
1.124     espie     926:        for (job = runningJobs; job != NULL; job = job->next) {
1.128     espie     927:                debug_kill_printf("passing to "
                    928:                    "child %ld running %s: %s\n", (long)job->pid,
                    929:                    job->node->name, really_kill(job, signo));
                    930:                may_remove_target(job);
1.2       deraadt   931:        }
1.1       deraadt   932:
1.124     espie     933:        if (signo == SIGINT && !touchFlag) {
1.78      espie     934:                if ((interrupt_node->type & OP_DUMMY) == 0) {
1.66      espie     935:                        ignoreErrors = false;
                    936:
1.124     espie     937:                        Job_Make(interrupt_node);
1.66      espie     938:                }
1.1       deraadt   939:        }
1.124     espie     940:        loop_handle_running_jobs();
1.131     espie     941:        internal_print_errors();
1.124     espie     942:
                    943:        /* die by that signal */
                    944:        sigprocmask(SIG_BLOCK, &sigset, NULL);
                    945:        signal(signo, SIG_DFL);
1.126     espie     946:        kill(getpid(), signo);
1.124     espie     947:        sigprocmask(SIG_SETMASK, &emptyset, NULL);
                    948:        /*NOTREACHED*/
1.131     espie     949:        fprintf(stderr, "This should never happen\n");
                    950:        exit(1);
1.1       deraadt   951: }
                    952:
                    953: /*
                    954:  *-----------------------------------------------------------------------
1.12      espie     955:  * Job_Finish --
1.1       deraadt   956:  *     Do final processing such as the running of the commands
1.6       millert   957:  *     attached to the .END target.
1.1       deraadt   958:  *
1.124     espie     959:  *     return true if fatal errors have happened.
1.1       deraadt   960:  *-----------------------------------------------------------------------
                    961:  */
1.124     espie     962: bool
1.56      espie     963: Job_Finish(void)
1.1       deraadt   964: {
1.134     espie     965:        bool problem = errorJobs != NULL;
1.124     espie     966:
1.116     espie     967:        if ((end_node->type & OP_DUMMY) == 0) {
1.134     espie     968:                if (problem) {
1.66      espie     969:                        Error("Errors reported so .END ignored");
                    970:                } else {
1.124     espie     971:                        Job_Make(end_node);
1.111     espie     972:                        loop_handle_running_jobs();
1.66      espie     973:                }
1.1       deraadt   974:        }
1.134     espie     975:        return problem;
1.1       deraadt   976: }
                    977:
1.124     espie     978: void
                    979: Job_Begin(void)
                    980: {
                    981:        if ((begin_node->type & OP_DUMMY) == 0) {
                    982:                Job_Make(begin_node);
                    983:                loop_handle_running_jobs();
                    984:        }
                    985: }
                    986:
1.1       deraadt   987: /*-
                    988:  *-----------------------------------------------------------------------
                    989:  * Job_Wait --
                    990:  *     Waits for all running jobs to finish and returns. Sets 'aborting'
                    991:  *     to ABORT_WAIT to prevent other jobs from starting.
                    992:  *
                    993:  * Side Effects:
                    994:  *     Currently running jobs finish.
                    995:  *
                    996:  *-----------------------------------------------------------------------
                    997:  */
                    998: void
1.56      espie     999: Job_Wait(void)
1.1       deraadt  1000: {
1.66      espie    1001:        aborting = ABORT_WAIT;
1.111     espie    1002:        loop_handle_running_jobs();
1.66      espie    1003:        aborting = 0;
1.1       deraadt  1004: }
                   1005:
                   1006: /*-
                   1007:  *-----------------------------------------------------------------------
                   1008:  * Job_AbortAll --
                   1009:  *     Abort all currently running jobs without handling output or anything.
                   1010:  *     This function is to be called only in the event of a major
1.124     espie    1011:  *     error.
1.1       deraadt  1012:  *
                   1013:  * Side Effects:
1.124     espie    1014:  *     All children are killed
1.1       deraadt  1015:  *-----------------------------------------------------------------------
                   1016:  */
                   1017: void
1.56      espie    1018: Job_AbortAll(void)
1.1       deraadt  1019: {
1.66      espie    1020:        Job *job;       /* the job descriptor in that element */
                   1021:        int foo;
1.6       millert  1022:
1.66      espie    1023:        aborting = ABORT_ERROR;
1.6       millert  1024:
1.124     espie    1025:        for (job = runningJobs; job != NULL; job = job->next) {
1.126     espie    1026:                killpg(job->pid, SIGINT);
                   1027:                killpg(job->pid, SIGKILL);
1.1       deraadt  1028:        }
1.6       millert  1029:
1.66      espie    1030:        /*
                   1031:         * Catch as many children as want to report in at first, then give up
                   1032:         */
1.117     espie    1033:        while (waitpid(WAIT_ANY, &foo, WNOHANG) > 0)
1.66      espie    1034:                continue;
1.2       deraadt  1035: }