suggested addition to 'date'

Brian Candler B.Candler at
Mon Aug 14 13:13:03 UTC 2006

On Fri, Aug 11, 2006 at 10:53:00PM -0700, Julian Elischer wrote:
> I tried making the signal handler just set a variable that makes the 
> main loop quit, flush and exit,
> but believe it or not, fgets() doesn't return from a signal. so you hit 
> ^C but it doesn't notice the flag that is set until
> you then hit CR.

Try using sigaction() instead of signal(), and don't set the SA_RESTART
flag. fgets() should then return with EINTR in that case.

OTOH, maybe stdio catches EINTR and retries itself. Quick check... no, it
doesn't, so it should work in the way you want. The attached program
demonstrates this.



----- 8< -----------------------------------------------------------------
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>

static int abortflag=0;

static void parent(int wfd, pid_t cpid)
    if (write(wfd, "abc", 3) != 3) { perror("write"); exit(1); }
    if (kill(cpid, SIGTERM) < 0) { perror("kill"); exit(1); }

static void setabort(int sig)

static void child(int rfd)
    char buf[256];
    struct sigaction act, oact;
    FILE *f = fdopen(rfd, "r");
    if (!f) { perror("fdopen"); exit(1); }

    memset(&act, 0, sizeof(act));
    act.sa_handler = setabort;
    sigaction(SIGTERM, &act, &oact);
    fprintf(stderr, "child: OK\n");
    while(fgets(buf, sizeof(buf), f)) {
        fprintf(stderr, "child: Abort flag = %d\n", abortflag);
        fprintf(stderr, "child: Got %d bytes: '%s'\n", strlen(buf), buf);
        if (abortflag) break;
    fprintf(stderr, "child: done\n");

int main(void)
    int pid;
    int fds[2];

    if (pipe(fds) < 0) { perror("pipe"); return 1; }
    pid = fork();
    if (pid < 0) { perror("fork"); return 1; }
    if (pid > 0)
        parent(fds[1], pid);
    return 0;

More information about the freebsd-current mailing list