?
Solved

How does this Pipe work?

Posted on 2003-02-25
6
Medium Priority
?
252 Views
Last Modified: 2010-03-05
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.

Thanks,

-Dan
0
Comment
Question by:dgoyette
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
  • 2
6 Comments
 
LVL 2

Accepted Solution

by:
perldork earned 200 total points
ID: 8020401
Actually,

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;
    close(MAIL);
    exit(0);
}

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




0
 
LVL 5

Expert Comment

by:PC_User321
ID: 8024327
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.
0
 

Author Comment

by:dgoyette
ID: 8025324
Excellent. That does answer my question. Thank you.
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
LVL 2

Expert Comment

by:perldork
ID: 8026486
Two processes are needed, but the explicit fork() is not
needed.

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.

0
 
LVL 5

Expert Comment

by:PC_User321
ID: 8028006
>> ... to then do an explicit fork() as well ...
There is no explicit fork.
0
 
LVL 2

Expert Comment

by:perldork
ID: 8028123
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!
0

Featured Post

VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

I've just discovered very important differences between Windows an Unix formats in Perl,at least 5.xx.. MOST IMPORTANT: Use Unix file format while saving Your script. otherwise it will have ^M s or smth likely weird in the EOL, Then DO NOT use m…
Checking the Alert Log in AWS RDS Oracle can be a pain through their user interface.  I made a script to download the Alert Log, look for errors, and email me the trace files.  In this article I'll describe what I did and share my script.
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…
Six Sigma Control Plans

771 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question