On Sun, Oct 18, 2009 at 03:50:17PM -0700, Philip Guenther wrote:
> On Sun, Oct 18, 2009 at 12:49 AM, Matt Fisher <[email protected]> wrote:
> > You're correct. I got started on this train of thought after reading
> > an old USENIX paper[1]. The line I suggested for deletion is identical
> > to what section 1.2.1 of that paper recommended should always be
> > included. Recent material continues to recommend such code, but not
> > specifically in OpenBSD[2],[3].
> >
> > Since such code is only rarely used in OpenBSD -- 9 occurrences in the
> > whole tree -- I thought it might be an obsolete or inapplicable
> > recommendation. One such occurrence was in m4/main.c, so I contacted the
> > developer who had recently checked in that file.
> >
> > I did read manuals, study code, consider, and test first. But I knew my
> > expertise was limited, and that there could be other considerations.
> 
> If all you have is a chunk of code that you don't understand the
> justification for, you have to work backwards to the problem.  This
> can turn into the programming equivalent of disproving an existential,
> for which having a broad base of experience really helps.  How do you
> get that base of experience?  Well, start by tackling concrete
> problems ("program behaves incorrectly when I try <blah>") instead of
> jumping straight to the abstract cases.
> 
> That, or you need to crank up your methodology and logic.  The code in
> this case applies only when the process is started with SIGINT set to
> SIG_IGN.  If the process was set by its parent to ignore SIGINT, why
> would it start paying attention to them now by catching them?  Doing
> that might be fine if that was something that used to be normal
> practice but never happened nowadays.  So what programs did that in
> the past?  Didn't the paper say something about running stuff in the
> background from the shell with "&"?  So let's check the sh(1) manpage
> to see what it says now:
>      When an asynchronous command is started when job
>      control is disabled (i.e. in most scripts), the command is started with
>      signals SIGINT and SIGQUIT ignored
> 
> Looks like the shell still does that.  A little bit of noodling shows
> that this snippet of shell script
>     #!/bin/sh
>     ( : ; /some/program/here ) &
> 
> Invokes /some/program/here with SIGINT ignored.
> 
> So, it looks like running m4 in the background from a shell script
> will still result in it being invoked with SIGINT set to SIG_IGN.  In
> such a case, if you interrupted the shell script using SIGINT,
> shouldn't m4 ignore the signal and continue?  It would continue if the
> shell script exited normally, so why should signaling the script
> terminate it?  Ergo, I think this code is correct and should be left
> as is.
> 
> You wonder why only 9 programs in the tree have such code.  Well, how
> programs does this problem apply to?  It doesn't apply to any program
> that calls daemon(), for example, as they won't get SIGINTs a
> terminal.  So rpc.statd's signal handling is fine, for example.  It
> also doesn't apply to programs that can't be usefully backgrounded, so
> 'rain' is fine as is.
> 
> But it looks like some programs do handle it wrong and could use
> fixing.  For example, 'sort' appears to be wrong...but before I wrote
> that I figured out how to trigger the problem, both to confirm it and
> to verify the fix.  Make sense?
> 
> Philip Guenther
> 
> 
> --- sort.c      22 Aug 2007 06:56:40 -0000      1.36
> +++ sort.c      18 Oct 2009 22:44:47 -0000
> @@ -273,7 +273,7 @@ main(int argc, char *argv[])
>                 outfile = outpath = toutpath;
>         } else if (!(ch = access(outpath, 0)) &&
>             strncmp(_PATH_DEV, outpath, 5)) {
> -               struct sigaction act;
> +               struct sigaction oact, act;
>                 int sigtable[] = {SIGHUP, SIGINT, SIGPIPE, SIGXCPU, SIGXFSZ,
>                     SIGVTALRM, SIGPROF, 0};
>                 int outfd;
> @@ -298,7 +298,9 @@ main(int argc, char *argv[])
>                 act.sa_flags = SA_RESTART;
>                 act.sa_handler = onsig;
>                 for (i = 0; sigtable[i]; ++i)   /* always unlink toutpath */
> -                       sigaction(sigtable[i], &act, 0);
> +                       if (sigaction(sigtable[i], NULL, &oact) ||
> +                           oact.sa_handler != SIG_IGN)
> +                               sigaction(sigtable[i], &act, NULL);

Ughh... I'm confused and I keep reading your explanation above
to no avail.

Are you saying that if parent of sort could set the signal
handler to something other than SIG_IGN, in that case sort
should not set its own handler? Wha...!?

Also, are you not making an assumption that call to sigaction()
in the if()-statement you added will not fail? i.e., wouldn't
this be safer ("more correct"):

+                       if (0 == sigaction(sigtable[i], NULL, &oact) &&
+                           oact.sa_handler != SIG_IGN)
+                               sigaction(sigtable[i], &act, NULL);

--patrick

Reply via email to