gnu@perl has asked for the wisdom of the Perl Monks concerning the following question:

I have written a simple Class for performing small alerting functions via email. What I was wondering is if I do this:
use My_Mailer; my $mailer = My_Mailer->new(); for (my $x=0;$x < 10;$x++) { unless (fork) { $mailer->initialisation_stuff(); $mailer->send(); exit; } }
Will each instance of $mailer in the children actually be the same object affecting the same data or will they be their own seperate entity containing only the data populated in $mailer up to the point of forking? In other words, if in one child I change/add something via a $mailer method, will it affect the other processes? It dosen't seem like it could, but I'm not sure. -Chad

Replies are listed 'Best First'.
Re: Objects and forking
by tilly (Archbishop) on Jul 10, 2003 at 17:56 UTC
    It depends on what happens in your new() method. If you open up a connection to the outside world, then the mail server will be likely to be confused as multiple children babble. If the connection is opened in your initialisation_stuff(), then each object will start off as separate clones.

    BTW your looping style is very C-ish. You will avoid most fencepost and off-by-one errors (both extremely common bugs) if you switch to the more Perlish:

    foreach my $x (0..9) { ... }
      Thanks, this is the way I thought it would work. The handle to sendmail is opened in each child when the send() method is called on the object.
      As for the looping, that is not what the code does (but thanks for the input just in case), it was just an little example. In actuality I load an array with the location of a bunch of config files and then fork to process each config file.
Re: Objects and forking
by Jenda (Abbot) on Jul 10, 2003 at 20:54 UTC

    I guess you only wrote it like this in this example, but just for reference, I've seen too many people ignoring errors. You should test the return value of the fork() better. It's a nonzero number in the parent, zero in the child and undef if the fork() failed!:

    my $pid = fork(); die "Ouch, can't fork: $^En\" unless defined $pid; unless ($pid) { ... }
    or if you want it to look more like your code:
    unless (my $pid = fork()) { die "Ouch, can't fork: $^En\" unless defined $pid; ... }

    Jenda
    Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live.
       -- Rick Osborne

    Edit by castaway: Closed small tag in signature

      Good point. The real code is much more involved than this tiny sample I threw in, but in the real thing I did forget to check and see if the fork even worked. Without checking if a fork failed, my program would seem to have run fine, no errors reported or anything.
Re: Objects and forking
by sauoq (Abbot) on Jul 10, 2003 at 21:01 UTC
    Will each instance of $mailer in the children actually be the same object affecting the same data or will they be their own seperate entity containing only the data populated in $mailer up to the point of forking?

    The latter.

    I think tilly was warning you against letting each child use the same connection. They would use the same connection if the connection was opened prior to the fork. You can prevent them from sharing a connection by opening any connections after forking. (I'm not even sure you are opening any connections at all, for that matter.)

    In other words, if in one child I change/add something via a $mailer method, will it affect the other processes?

    No. It won't.

    -sauoq
    "My two cents aren't worth a dime.";
    
      Tilly verified what I was thinking, from the point of the call to fork each entity is a seperate thing as far as data within it goes. File handles are another story though, since they are inherited from parent to child it would be a mess when the children went to send any output to them.
      What I am doing is creating an object containing some generic data (email addresses, subject, etc) that will be common amongst all children. Each child process will add its own pertinent information and do what it needs to with the object. Basically send an email alert with it's own data in the body of the email, but each child has the same 'To:' and 'Subject:'.