Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 14 Aug 2006 14:12:51 +0100
From:      Brian Candler <B.Candler@pobox.com>
To:        Julian Elischer <julian@elischer.org>
Cc:        Giorgos Keramidas <keramida@ceid.upatras.gr>, current@freebsd.org
Subject:   Re: suggested addition to 'date'
Message-ID:  <20060814131251.GB85695@uk.tiscali.com>
In-Reply-To: <44DD6CBC.9030309@elischer.org>
References:  <44DD4510.5070002@elischer.org> <20060812033607.GB80768@gothmog.pc> <44DD50FF.5040406@elischer.org> <20060812041535.GA82669@gothmog.pc> <44DD5992.5080409@elischer.org> <20060812045622.GA84354@gothmog.pc> <44DD6CBC.9030309@elischer.org>

next in thread | previous in thread | raw e-mail | index | archive | help
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.

Regards,

Brian.

----- 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); }
    sleep(1);
    if (kill(cpid, SIGTERM) < 0) { perror("kill"); exit(1); }
    sleep(4);
    close(wfd);
}

static void setabort(int sig)
{
    abortflag=1;
}

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;
    }
    fclose(f);
    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);
    else
        child(fds[0]);
    return 0;
}



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20060814131251.GB85695>