Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

Re^4: Socket descriptor passed across fork -- hanging

by dd-b (Monk)
on Oct 13, 2011 at 17:47 UTC ( [id://931345]=note: print w/replies, xml ) Need Help??


in reply to Re^3: Socket descriptor passed across fork -- hanging
in thread Socket descriptor passed across fork -- hanging

They closed their socket without sending \n, yes. Shit happens in the real world; possibly encouraged by servers being generous in what they accept.

I guess I misread the code or your description of the protocol, sorry.

What are the tradeoffs of using sysread/syswrite vs. read/print? The obvious one is I have to implement my own line-oriented read for the first line of the protocol, which I have to read and parse. Is dropping down a level going to be of significant benefit, and if so in what?

I've been finding various strange returns from $sock->read(), including undef with $! empty. However, by taking a desperate leap and treating all errors except EINTR and EAGAIN as end-of-file, my proxy is now successfully passing data back and forth between test clients and real servers (next step will be to more aggressive test clients, and then real clients). For the proxy, treating a read error as EOF isn't really too bad a choice, clearly it's time to close that connection and terminate the proxy child!

  • Comment on Re^4: Socket descriptor passed across fork -- hanging

Replies are listed 'Best First'.
Re^5: Socket descriptor passed across fork -- hanging
by Marshall (Canon) on Oct 15, 2011 at 10:28 UTC
    I guess I should explain, that I started with C code and then said, "hey, what would this look like in Perl for the fun of it". I was able to any combination working together. C server/Perl Client, Perl Server/C client or both each way.

    You brought up some good points, one is the "or next" in the accept().
    You say in the code that the "next" if accept returns undef isn't necessary any more, but I've seen my $listen->accept() call return EINTR (perl 5.8.8, Linux 2.6.18), so it seems to be necessary still here. I agree with you and would leave the code as is - my comment is wrong.

    Yes, I would close the sockets that aren't going to be used! This is cheap and solves problems!

    For example, as a parent (the server) after I have forked off a child, I am not going to talk on the active socket. That is the child's job. One reason to close it is assist in freeing resources. If the child decides to hang up on the client close the active socket, then we don't have to worry about what kind of weird stuff might or might not happen because I still have it open in a parent.

    We get into a similar sort of a thing if the child doesn't close the passive socket. We don't want children somehow running off making grandchildern! A child's job is to talk to one client. If somehow some kid had a baby then we have some dual role stuff going on and there can be issues with who reaps who when who dies. "close($passive)"; closes off a lot of possible nasty things at very little cost.

    Keep the fork architecture "clean":
    Parents only listen for new clients, they make a new child to deal with the new client and then go back to listening.

    Children only talk to the client that they are connected to. They die when the need for them to talk to that client goes away. The parent who started them is notified when they die.

    I've been finding various strange returns from $sock->read(), including undef with $! empty. Yes there can be strange things. $! is only set only an error. It is not reset if there is no error. I think in some circumstances undef is just considered "normal status" and is not an error. This is true in the C interface where there is of course no such thing as "undef".

    Systems programming is complicated stuff and there are lots of timing related "yeah but's".

Re^5: Socket descriptor passed across fork -- hanging
by Marshall (Canon) on Oct 15, 2011 at 17:26 UTC
    What are the tradeoffs of using sysread/syswrite vs. read/print? The obvious one is I have to implement my own line-oriented read for the first line of the protocol, which I have to read and parse. Is dropping down a level going to be of significant benefit, and if so in what?

    This is a good question. Perhaps some other Monks will chime in here..

    If you read my code and can see where it can go..Implementing a line oriented protocol is not hard. You have a non-standard "\n" termination of the line but you just check the last character for "\n" to see if the line is finished. $buf is a string, not an array, so you can use a substr() operation, or just run a regex on the $buf chars to see if the last char is "\n";

    The big difference between sysread and read is non-buffered vs buffered. This might lead to lower performance when many lines are being sent at once. Depends upon how smart the readn() is.

    However, it sounds to me like you just need to implement a server that talks with some clients over which you have no control. And if the performance is adequate and if your server's reliability is rock solid, I would "stick a fork in it" and say its done! Normally for something like this: reliability is the main thing...Doesn't crash..doesn't loose data..recovers when a client crashes..function is 100% great in all respects.

    I see ways to make this faster, but if that is not necessary, then you are loosing the argument.

    Kick ass with less than one page of Perl code and go!

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://931345]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others imbibing at the Monastery: (5)
As of 2024-04-19 20:07 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found