diff options
author | Marc Espie <espie@cvs.openbsd.org> | 2012-10-06 09:32:41 +0000 |
---|---|---|
committer | Marc Espie <espie@cvs.openbsd.org> | 2012-10-06 09:32:41 +0000 |
commit | 6995c894e9430aea10eb447043fd167cd7e14f85 (patch) | |
tree | 9d7b5121e5ee9dc1781a87acf9dae5c17d15e636 /usr.bin/make | |
parent | 729956d7a1b6d7803a8676e8c1e6cb2a94a21898 (diff) |
- extra juice for debugging signal passing. Note when we can't pass the
signal because the process already bought it (pgroups will do that to you)
(lots of discussion with Todd on that one)
- tweak error handling some more to make it less verbose when just one job
is running...
- show signal name in case of signal interrupts.
- zap OP_LIB, move that stuff to the location where we warn when we meet
that bug.
okay millert@
Diffstat (limited to 'usr.bin/make')
-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)) |