[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.163

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