diff options
-rw-r--r-- | usr.bin/make/defines.h | 3 | ||||
-rw-r--r-- | usr.bin/make/engine.c | 48 | ||||
-rw-r--r-- | usr.bin/make/engine.h | 5 | ||||
-rw-r--r-- | usr.bin/make/gnode.h | 3 | ||||
-rw-r--r-- | usr.bin/make/job.c | 229 | ||||
-rw-r--r-- | usr.bin/make/main.c | 7 | ||||
-rw-r--r-- | usr.bin/make/targ.c | 10 |
7 files changed, 162 insertions, 143 deletions
diff --git a/usr.bin/make/defines.h b/usr.bin/make/defines.h index a0b20860d48..c7438cc6948 100644 --- a/usr.bin/make/defines.h +++ b/usr.bin/make/defines.h @@ -1,7 +1,7 @@ #ifndef DEFINES_H #define DEFINES_H -/* $OpenBSD: defines.h,v 1.11 2012/09/21 07:55:20 espie Exp $ */ +/* $OpenBSD: defines.h,v 1.12 2012/10/06 09:32:40 espie Exp $ */ /* * Copyright (c) 2001 Marc Espie. @@ -98,6 +98,7 @@ extern int debug; #define DEBUG_NAME_MATCHING 0x2000 #define DEBUG_QUICKDEATH 0x4000 #define DEBUG_EXPENSIVE 0x8000 +#define DEBUG_KILL 0x10000 #define CONCAT(a,b) a##b diff --git a/usr.bin/make/engine.c b/usr.bin/make/engine.c index db622180df5..ff5c70f5092 100644 --- a/usr.bin/make/engine.c +++ b/usr.bin/make/engine.c @@ -1,4 +1,4 @@ -/* $OpenBSD: engine.c,v 1.35 2012/10/04 13:20:46 espie Exp $ */ +/* $OpenBSD: engine.c,v 1.36 2012/10/06 09:32:40 espie Exp $ */ /* * Copyright (c) 2012 Marc Espie. * @@ -99,6 +99,24 @@ static void setup_engine(void); static char **recheck_command_for_shell(char **); static void list_parents(GNode *, FILE *); +/* XXX due to a bug in make's logic, targets looking like *.a or -l* + * have been silently dropped when make couldn't figure them out. + * Now, we warn about them until all Makefile bugs have been fixed. + */ +static bool +drop_silently(const char *s) +{ + size_t len; + + if (s[0] == '-' && s[1] == 'l') + return true; + + len = strlen(s); + if (len >=2 && s[len-2] == '.' && s[len-1] == 'a') + return true; + return false; +} + bool node_find_valid_commands(GNode *gn) { @@ -111,11 +129,10 @@ node_find_valid_commands(GNode *gn) gn->type |= OP_SILENT; if (OP_NOP(gn->type) && Lst_IsEmpty(&gn->commands)) { - /* XXX */ - if ((gn->type & OP_LIB)) { + if (drop_silently(gn->name)) { printf("Warning: target %s", gn->name); list_parents(gn, stdout); - printf(" does not have any command\n"); + printf(" does not have any command (BUG)\n"); return true; } /* @@ -586,11 +603,22 @@ job_attach_node(Job *job, GNode *node) job->exit_type = JOB_EXIT_OKAY; job->location = NULL; job->flags = 0; + job->sent_signal = 0; } void job_handle_status(Job *job, int status) { + bool silent; + + /* if there's one job running and we don't keep going, no need + * to report right now. + */ + if ((job->flags & JOB_ERRCHECK) && !keepgoing && runningJobs == NULL) + silent = !DEBUG(JOB); + else + silent = false; + debug_job_printf("Process %ld (%s) exited with status %d.\n", (long)job->pid, job->node->name, status); @@ -598,26 +626,30 @@ job_handle_status(Job *job, int status) if (WIFEXITED(status)) { job->code = WEXITSTATUS(status);/* exited */ if (status != 0) { - printf("*** Error code %d", job->code); + if (!silent) + printf("*** Error %d", job->code); job->exit_type = JOB_EXIT_BAD; } else job->exit_type = JOB_EXIT_OKAY; } else { job->exit_type = JOB_SIGNALED; job->code = WTERMSIG(status); /* signaled */ - printf("*** Signal %d", job->code); + if (!silent) + printf("*** Signal %d", job->code); } /* if there is a problem, what's going on ? */ if (job->exit_type != JOB_EXIT_OKAY) { - printf(" in target %s", job->node->name); + if (!silent) + printf(" in target '%s'", job->node->name); if (job->flags & JOB_ERRCHECK) { job->node->built_status = ERROR; /* compute expensive status if we really want it */ if ((job->flags & JOB_SILENT) && job == &myjob) determine_expensive_job(job); if (!keepgoing) { - printf("\n"); + if (!silent) + printf("\n"); job->next = errorJobs; errorJobs = job; /* XXX don't free the command */ diff --git a/usr.bin/make/engine.h b/usr.bin/make/engine.h index 74fa2ed482a..31ca704ba11 100644 --- a/usr.bin/make/engine.h +++ b/usr.bin/make/engine.h @@ -1,6 +1,6 @@ #ifndef ENGINE_H #define ENGINE_H -/* $OpenBSD: engine.h,v 1.10 2012/09/21 07:55:20 espie Exp $ */ +/* $OpenBSD: engine.h,v 1.11 2012/10/06 09:32:40 espie Exp $ */ /* * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. @@ -97,6 +97,7 @@ struct Job_ { #define JOB_EXIT_OKAY 0 #define JOB_EXIT_BAD 1 #define JOB_SIGNALED 2 + int sent_signal; int code; /* exit status or signal code */ LstNode next_cmd; /* Next command to run */ char *cmd; /* Last command run */ @@ -104,8 +105,8 @@ struct Job_ { unsigned short flags; #define JOB_SILENT 0x001 /* Command was silent */ #define JOB_IS_EXPENSIVE 0x002 +#define JOB_LOST 0x004 /* sent signal to non-existing pid ? */ #define JOB_ERRCHECK 0x008 /* command wants errcheck */ -#define JOB_MINE 0x010 /* XXX special job run by compat */ }; extern bool job_run_next(Job *); diff --git a/usr.bin/make/gnode.h b/usr.bin/make/gnode.h index b24330b286a..bf225880a07 100644 --- a/usr.bin/make/gnode.h +++ b/usr.bin/make/gnode.h @@ -1,6 +1,6 @@ #ifndef GNODE_H #define GNODE_H -/* $OpenBSD: gnode.h,v 1.21 2012/10/02 10:29:30 espie Exp $ */ +/* $OpenBSD: gnode.h,v 1.22 2012/10/06 09:32:40 espie Exp $ */ /* * Copyright (c) 2001 Marc Espie. @@ -230,7 +230,6 @@ struct command /* Attributes applied by PMake */ #define OP_TRANSFORM 0x00040000 /* The node is a transformation rule */ #define OP_MEMBER 0x00080000 /* Target is a member of an archive */ -#define OP_LIB 0x00100000 /* Target is a library */ #define OP_ARCHV 0x00200000 /* Target is an archive construct */ #define OP_HAS_COMMANDS 0x00400000 /* Target has all the commands it should. * Used when parsing to catch multiple diff --git a/usr.bin/make/job.c b/usr.bin/make/job.c index fab39a6dc82..ed2ea5ecf82 100644 --- a/usr.bin/make/job.c +++ b/usr.bin/make/job.c @@ -1,4 +1,4 @@ -/* $OpenBSD: job.c,v 1.127 2012/10/04 13:20:46 espie Exp $ */ +/* $OpenBSD: job.c,v 1.128 2012/10/06 09:32:40 espie Exp $ */ /* $NetBSD: job.c,v 1.16 1996/11/06 17:59:08 christos Exp $ */ /* @@ -131,16 +131,14 @@ Job *errorJobs; /* Jobs in error at end */ static Job *heldJobs; /* Jobs not running yet because of expensive */ static pid_t mypid; -static volatile sig_atomic_t got_fatal, got_other; +static volatile sig_atomic_t got_fatal; static volatile sig_atomic_t got_SIGINT, got_SIGHUP, got_SIGQUIT, got_SIGTERM, - got_SIGINFO, got_SIGTSTP, got_SIGTTOU, got_SIGTTIN, got_SIGCONT, - got_SIGWINCH; + got_SIGINFO; static sigset_t sigset, emptyset; static void handle_fatal_signal(int); -static void pass_job_control_signal(int); static void handle_siginfo(void); static void postprocess_job(Job *, bool); static Job *prepare_job(GNode *); @@ -157,22 +155,72 @@ static bool expensive_command(const char *); static void setup_signal(int); static void notice_signal(int); static void setup_all_signals(void); -static void setup_job_control_interrupts(void); -static void killcheck(pid_t, int); +static const char *really_kill(Job *, int); +static void kill_with_sudo_maybe(pid_t, int, const char *); +static void debug_kill_printf(const char *, ...); +static void debug_vprintf(const char *, va_list); +static void may_remove_target(Job *); -static void -killcheck(pid_t pid, int signo) +static void +kill_with_sudo_maybe(pid_t pid, int signo, const char *p) { - if (kill(pid, signo) == 0) + char buf[32]; /* largely enough */ + + for (;*p != '\0'; p++) { + if (*p != 's') + continue; + if (p[1] != 'u') + continue; + p++; + if (p[1] != 'd') + continue; + p++; + if (p[1] != 'o') + continue; + snprintf(buf, sizeof buf, "sudo -n /bin/kill -%d %ld", + signo, (long)pid); + debug_kill_printf("trying to kill with %s", buf); + system(buf); return; + } + +} + +static const char * +really_kill(Job *job, int signo) +{ + pid_t pid = job->pid; + job->sent_signal = signo; + if (getpgid(pid) != getpgrp()) { + if (killpg(pid, signo) == 0) + return "group got signal"; + pid = -pid; + } else { + if (kill(pid, signo) == 0) + return "process got signal"; + } if (errno == ESRCH) { - fprintf(stderr, - "Can't send signal %d to %ld: pid not found\n", - signo, (long)pid); + job->flags |= JOB_LOST; + return "not found"; } else if (errno == EPERM) { - fprintf(stderr, - "Can't send signal %d to %ld: not permitted\n", - signo, (long)pid); + kill_with_sudo_maybe(pid, signo, job->cmd); + return ""; + } +} + +static void +may_remove_target(Job *j) +{ + if ((j->sent_signal == SIGINT || j->sent_signal == SIGQUIT || + j->sent_signal == SIGHUP || j->sent_signal == SIGTERM) + && !noExecute && !Targ_Precious(j->node)) { + const char *file = Var(TARGET_INDEX, j->node); + int r = eunlink(file); + + if (DEBUG(JOB) && r == -1) + fprintf(stderr, " *** would unlink %s\n", file); + if (r != -1) + fprintf(stderr, " *** %s removed\n", file); } } @@ -181,25 +229,34 @@ print_error(Job *j, Job *k) { const char *type; - if (j->exit_type == JOB_EXIT_BAD) - type = "Exit status"; - else if (j->exit_type == JOB_SIGNALED) - type = "Received signal"; - else - type = "Should not happen"; - fprintf(stderr, " %s %d (", type, j->code); - fprintf(stderr, "line %lu", - j->location->lineno); + if (j->exit_type == JOB_EXIT_BAD) { + fprintf(stderr, "*** Error %d", j->code); + if (j->sent_signal != 0 && j->code == j->sent_signal + 128) + fprintf(stderr, " (SIG%s in shell)", + sys_signame[j->sent_signal]); + } else if (j->exit_type == JOB_SIGNALED) { + if (j->code < NSIG) + fprintf(stderr, "*** SIG%s", + sys_signame[j->code]); + else + fprintf(stderr, "*** unknown signal %d", j->code); + } else + fprintf(stderr, "*** Should not happen %d", j->code); + if (DEBUG(KILL) && (j->flags & JOB_LOST)) + fprintf(stderr, "!"); + fprintf(stderr, " (line %lu", j->location->lineno); if (j == k) fprintf(stderr, " of %s,", j->location->fname); else fputs(",", stderr); if ((j->flags & (JOB_SILENT | JOB_IS_EXPENSIVE)) == JOB_SILENT) - fprintf(stderr, "\n target %s: %s", j->node->name, j->cmd); + fprintf(stderr, "\n target '%s': %s", j->node->name, + j->cmd); else - fprintf(stderr, " target %s", j->node->name); + fprintf(stderr, " target '%s'", j->node->name); fputs(")\n", stderr); free(j->cmd); + may_remove_target(j); } void @@ -260,37 +317,9 @@ notice_signal(int sig) break; case SIGCHLD: break; - case SIGTSTP: - got_SIGTSTP++; - got_other = 1; - break; - case SIGTTOU: - got_SIGTTOU++; - got_other = 1; - break; - case SIGTTIN: - got_SIGTTIN++; - got_other = 1; - break; - case SIGCONT: - got_SIGCONT++; - got_other = 1; - break; - case SIGWINCH: - got_SIGWINCH++; - got_other = 1; - break; } } -static void -setup_job_control_interrupts(void) -{ - setup_signal(SIGTSTP); - setup_signal(SIGTTOU); - setup_signal(SIGTTIN); -} - void setup_all_signals(void) { @@ -309,7 +338,6 @@ setup_all_signals(void) /* Have to see SIGCHLD */ setup_signal(SIGCHLD); got_fatal = 0; - got_other = 0; } static void @@ -349,29 +377,6 @@ handle_all_signals(void) { if (got_SIGINFO) handle_siginfo(); - while (got_other) { - got_other = 0; - if (got_SIGWINCH) { - got_SIGWINCH=0; - pass_job_control_signal(SIGWINCH); - } - if (got_SIGTTIN) { - got_SIGTTIN=0; - pass_job_control_signal(SIGTTIN); - } - if (got_SIGTTOU) { - got_SIGTTOU=0; - pass_job_control_signal(SIGTTOU); - } - if (got_SIGTSTP) { - got_SIGTSTP=0; - pass_job_control_signal(SIGTSTP); - } - if (got_SIGCONT) { - got_SIGCONT=0; - pass_job_control_signal(SIGCONT); - } - } while (got_fatal) { got_fatal = 0; aborting = ABORT_INTERRUPT; @@ -395,15 +400,32 @@ handle_all_signals(void) } } +static void +debug_vprintf(const char *fmt, va_list va) +{ + (void)printf("[%ld] ", (long)mypid); + (void)vprintf(fmt, va); + fflush(stdout); +} + void debug_job_printf(const char *fmt, ...) { if (DEBUG(JOB)) { va_list va; - (void)printf("[%ld] ", (long)mypid); va_start(va, fmt); - (void)vprintf(fmt, va); - fflush(stdout); + debug_vprintf(fmt, va); + va_end(va); + } +} + +static void +debug_kill_printf(const char *fmt, ...) +{ + if (DEBUG(KILL)) { + va_list va; + va_start(va, fmt); + debug_vprintf(fmt, va); va_end(va); } } @@ -787,33 +809,6 @@ Job_Empty(void) return runningJobs == NULL; } -static void -pass_job_control_signal(int signo) -{ - Job *job; - - debug_job_printf("pass_job_control_signal(%d) called.\n", signo); - - - for (job = runningJobs; job != NULL; job = job->next) { - debug_job_printf("pass_job_control_signal to " - "child %ld running %s.\n", (long)job->pid, - job->node->name); - killcheck(job->pid, signo); - } - /* after forwarding the signal, those should interrupt us */ - if (signo == SIGTSTP || signo == SIGTTOU || signo == SIGTTIN) { - sigprocmask(SIG_BLOCK, &sigset, NULL); - signal(signo, SIG_DFL); - kill(getpid(), signo); - sigprocmask(SIG_SETMASK, &emptyset, NULL); - } - /* SIGWINCH is irrelevant for us, SIGCONT must put back normal - * handling for other job control signals */ - if (signo == SIGCONT) - setup_job_control_interrupts(); -} - /*- *----------------------------------------------------------------------- * handle_fatal_signal -- @@ -829,20 +824,14 @@ handle_fatal_signal(int signo) { Job *job; - debug_job_printf("handle_fatal_signal(%d) called.\n", signo); + debug_kill_printf("handle_fatal_signal(%d) called.\n", signo); for (job = runningJobs; job != NULL; job = job->next) { - if (!Targ_Precious(job->node)) { - const char *file = Var(TARGET_INDEX, job->node); - - if (!noExecute && eunlink(file) != -1) - Error("*** %s removed", file); - } - debug_job_printf("handle_fatal_signal: passing to " - "child %ld running %s.\n", (long)job->pid, - job->node->name); - killcheck(job->pid, signo); + debug_kill_printf("passing to " + "child %ld running %s: %s\n", (long)job->pid, + job->node->name, really_kill(job, signo)); + may_remove_target(job); } if (signo == SIGINT && !touchFlag) { diff --git a/usr.bin/make/main.c b/usr.bin/make/main.c index 4aca9e7a0d8..5412f9ed0da 100644 --- a/usr.bin/make/main.c +++ b/usr.bin/make/main.c @@ -1,4 +1,4 @@ -/* $OpenBSD: main.c,v 1.97 2012/10/02 10:29:31 espie Exp $ */ +/* $OpenBSD: main.c,v 1.98 2012/10/06 09:32:40 espie Exp $ */ /* $NetBSD: main.c,v 1.34 1997/03/24 20:56:36 gwr Exp $ */ /* @@ -263,11 +263,14 @@ MainParseArgs(int argc, char **argv) } break; case 'j': - debug |= DEBUG_JOB; + debug |= DEBUG_JOB | DEBUG_KILL; break; case 'J': /* ignore */ break; + case 'k': + debug |= DEBUG_KILL; + break; case 'l': debug |= DEBUG_LOUD; break; diff --git a/usr.bin/make/targ.c b/usr.bin/make/targ.c index b55de852b99..d89eada51d5 100644 --- a/usr.bin/make/targ.c +++ b/usr.bin/make/targ.c @@ -1,4 +1,4 @@ -/* $OpenBSD: targ.c,v 1.67 2012/10/02 10:29:31 espie Exp $ */ +/* $OpenBSD: targ.c,v 1.68 2012/10/06 09:32:40 espie Exp $ */ /* $NetBSD: targ.c,v 1.11 1997/02/20 16:51:50 christos Exp $ */ /* @@ -150,12 +150,7 @@ Targ_NewGNi(const char *name, const char *ename) gn = ohash_create_entry(&gnode_info, name, &ename); gn->path = NULL; - if ((name[0] == '-' && name[1] == 'l') || - (ename - name >=2 && ename[-1] == 'a' && ename[-2] == '.')) - gn->type = OP_LIB; - else - gn->type = 0; - + gn->type = 0; gn->special = SPECIAL_NONE; gn->unmade = 0; gn->must_make = false; @@ -290,7 +285,6 @@ Targ_PrintType(int type) PRINTBIT(JOIN); PRINTBIT(INVISIBLE); PRINTBIT(NOTMAIN); - PRINTDBIT(LIB); /*XXX: MEMBER is defined, so CONCAT(OP_,MEMBER) gives OP_"%" */ case OP_MEMBER: if (DEBUG(TARG)) |