简体   繁体   中英

Perl fork why not having the carriage return/line feed breaks the code?

Anyone can enlighten me about the great mystery of why this code works smoothly:

#!/usr/bin/perl

my $papa = $$;
my $pid;
$pid = fork;
die "Fork call has failed: $!" unless defined $pid;

if ($pid) {
    # Dad code
    while (1) {
        print "Fix your room Charlie\n";
        sleep(1);
    }

} else {
    # Child code
    for ( my $count = 0; $count < 5; $count++ ) {
        print "Oh, not now dad...\n";
        sleep(1);
    }
    local $SIG{TERM} = "IGNORE";
    kill TERM => -$papa;
    exit;
}

But if I remove the jumping to the next line it suddenly does not?

#!/usr/bin/perl

my $papa = $$;
my $pid;
$pid = fork;
die "Fork call has failed: $!" unless defined $pid;

if ($pid) {
    # Dad code
    while (1) {
        print "Fix your room Charlie";
        sleep(1);
    }

} else {
    # Child code
    for ( my $count = 0; $count < 5; $count++ ) {
        print "Not now dad...\n";
        sleep(1);
    }
    local $SIG{TERM} = "IGNORE";
    kill TERM => -$papa;
    exit;
}

It may be something really stupid, or it my have a reason that would help me to understand better the inners of print... or the inners of fork (I know, a child killing its dad is not nice, but notice the father had entered an infinite loop)

Thanks in advance :)

Your problem boils down to the following:

$ perl -e'print "FOO\n"; kill TERM => $$'
FOO
Terminated

$ perl -e'print "FOO";   kill TERM => $$'
Terminated

You're suffering from buffering.

STDOUT is line-buffered when connected to a terminal. That means it will flush when a newline is output, when the buffer becomes full and on a graceful exit. In the first program, that happens before you send the signal. In the latter, that would happen after you send the signal.

Flush the output explicitly

$ perl -e'print "FOO"; select->flush(); kill TERM => $$'
FOOTerminated

Or cause the output to be flushed for each print

$ perl -e'$|=1; print "FOO"; kill TERM => $$'
FOOTerminated

You're suffering from buffering.

Set your $OUTPUT_FLUSH to ensure the print doesn't wait until a newline before outputting:

local $| = 1; # Flush output

# Dad code
while (1) {
    print "Fix your room Charlie";
    sleep(1);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM