Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 256
  • Last Modified:

How does this Pipe work?

I have been reviewing another person's code (a more experienced developer than I am), and am somewhat baffled by the subroutine he is using to send email. Here is the subroutine:


sub mail {
    my ($to, $from, $subject, $body, $extra_headers_href) = @_;

    $SIG{CHLD} = "IGNORE";

    my $pid = open(MAIL, "|-");

    if (!defined($pid)) {
        die("Couldn't fork");

    if ($pid == 0) {
        # We're the child
        exec("/usr/sbin/sendmail", "-t", "-f$from");
    } else {
        # We're the parent
        print MAIL "From: $from\nTo: $to\nSubject: $subject\n\n";
        print MAIL $body;
        close MAIL;
        return 1;


What I really don't understand is how the pipe works, specifically, how the parent knows to write the mail information to MAIL before the child executes sendmail.

Will the child always execute after the parent has finished? In my testing, I am unable to tell.

This is just kind of confusing me, so if anyone could lend some advice as to how the child knows to wait for the parent to finish writing to MAIL before sending the email, I would be happily enlightended.


  • 3
  • 2
1 Solution

The parent doesn't know that :) .. sendmail, when used in this manner, will read from STDIN until it receives an EOF character .. then it will process the mail it has received.

When using fork, it is not guaranteed that the child will be created before the code the parent executes is run .. so it would be possible for the parent to start writing before the child is ready to accept the input ..

However, unless IO is set to be unbuffered, this should not be an issue, as the OS/perl will buffer some amount of text internally before sending it to the pipe.

Still, that code snippet doesn't make a lot of sense ... if the goal is to have the mail process not keep the main program from executing the pipe and mail send should be all done in the child .. the way it is done above the main program will still have to wait for the mail command to complete before continuing ...

Doing it in the style below would let the mail command run "asynchronously" ...

my $pid = fork();

if ($pid == 0) { # Child
    open(MAIL,"blah blah") || die "open failed: $!\n";
    print MAIL $stuff;
    print MAIL $more_stuff;

#  This part of the program will continue while sendmail does its' work in the child.

Two processes are needed - one to run sendmail and the other to pump information into it.
The fork gives you the two processes, and the required data path between them.
dgoyetteAuthor Commented:
Excellent. That does answer my question. Thank you.
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

Two processes are needed, but the explicit fork() is not

doing an open(SYMBOL,"cmd |")

causes perl to create the needed pipes and do the fork
exec pair for the child process, so the only reason to
then do an explicit fork() as well is to allow the mail to be sent and not have the main program have to wait for the sendmail command to complete.

>> ... to then do an explicit fork() as well ...
There is no explicit fork.
You are right, there isn't .. my bad.

That still seems like the hard way to do things .. as opposed to doing what I thought i saw ;) ..

open(MAIL,"cmd |");

which does the fork/exec for the user.

I sure did see just what I wanted to while reading that ... man, time to get the eyes checked!

Featured Post

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 3
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now