jhc@m2var2.uucp (James H. Coombs) (08/02/90)
I normally have servers fork after accepting connections. I am trying to use RPC, but I don't see anything in the documentation about forking. I also don't see any good hooks in the API. Thanks for any suggestions. --Jim
peters@mips2.cr.bull.com (Dan Peters) (08/07/90)
In article <46413@brunix.UUCP> jhc@iris.brown.edu (Jim Coombs) writes: >I normally have servers fork after accepting connections. I am trying >to use RPC, but I don't see anything in the documentation about >forking. I also don't see any good hooks in the API. > >Thanks for any suggestions. --Jim I have used NFS's RPC (Sun Microsystems) to provide an application with remote access to library functions resident on another machine. The user application is linked with my RPC client code on the local machine while I link the library into my RPC server code on the remote machine. The RPC 'library' server must be started up first on the remote machine then the 'application' may be executed on the local machine. Upon the first library call that the local application makes, my RPC client code (linked with the local application in place of the library) performs all of the RPC set-up (client create, etc.) AND makes a first-time RPC call over the newly established client transport to tell the server to fork. After the success of this INITIAL remote procedure call, the RPC client/server set-up overhead is complete. Now RPC is used to transparently access the remote library for the application's first library call. Subsequent library calls by the application also result in RPC to the server but without the initial first-time overhead. All this set-up is done transparent to the local application during what it thinks is only the first library call. RPC servers use 2 sockets: ONE to originally created by 'svctcp_create' to receive client connection requests over and when such a connection is received by the server, the socket 'accept' call actually creates ANOTHER socket over which all subsequent communication (procedure calls) takes place. After the fork: The Parent server process must close the 'accept' created socket, keeping open only the original 'svctcp_create' created socket over which it received the client connect request. (The Parent in this role is a daemon process that stays active only to accept client connections and forks a child server to service the client and nothing else.) The Child server process must close the 'svctcp_create' created socket keeping open only the 'accept' created socket over which it will receive all subsequent remote procedure calls. (The Child in this role is the functional RPC server handling all procedure calls from the application client EXCEPT the INITIAL remote procedure call to fork the server.) This Child server process will exit when it's 'accepted' socket connection is closed by the client application on the local machine. The socket will be closed by the client application on the local machine as a result of it normal exit. I hope my experience is helpful to you, Dan Peters -- == Dan Peters Bull HN Information Systems Inc. == (508) 294-3325 (294-3020) 300 Concord Road MS 826a == peters@mips2.cr.bull.com Billerica, MA 01821
jhc@m2jhc.uucp (James H. Coombs) (08/09/90)
In article <1990Aug6.214016.24874@mips2.cr.bull.com> peters@mips2.cr.bull.com (Dan Peters) writes: > Upon the first library call that the local application makes, my RPC >client code (linked with the local application in place of the library) >performs all of the RPC set-up (client create, etc.) AND makes a first-time >RPC call over the newly established client transport to tell the server >to fork. An elegant solution! I did try having my database Open routine fork(), but the process crashed. I assumed that the problem was due to the failure of the Open routine to return the specified results. Perhaps using a void would have prevented that problem (or it was something else). I also was not closing the sockets that were irrelevant to the parent/child. > The Parent server process must close the 'accept' created socket, >keeping open only the original 'svctcp_create' created socket over which it >received the client connect request. I discovered this when I went into the 4.0 code and added a fork() immediately after the accept() [in rendezvous_request()]. Exactly what do you have the parent close() in your high-level approach? > The Child server process must close the 'svctcp_create' created >socket keeping open only the 'accept' created socket over which it will >receive all subsequent remote procedure calls. Same question---how does the child find the parent's socket? > This Child server process will exit when it's 'accepted' socket >connection is closed by the client application on the local machine. This was not happening for me in my low-level approach. Should it be automatic? In my socket work, servers block on a read for the next command. I usually detect the loss of a connection by noting that the block has been released but the socket is empty. SIGPIPE will be raised only if I attempt to write to the socket. I occasionally get "Connection reset by peer" or "Not a typewriter", but the circumstances are not that clear to me. If someone turns a machine off without rebooting it, then the server will block forever unless I use the keepalive option. Does RPC do something to handle the broken connection automatically? Thanks for the information. --Jim