[systemd-devel] sd_listen_fds: find file descriptor

Michael D. Berger m.d.berger at ieee.org
Fri Dec 16 16:48:05 PST 2011


> -----Original Message-----
> From: Lennart Poettering [mailto:lennart at poettering.net] 
> Sent: Friday, December 16, 2011 09:40
> To: Michael D. Berger
> Cc: systemd-devel at lists.freedesktop.org
> Subject: Re: [systemd-devel] sd_listen_fds: find file descriptor
> 
> On Thu, 15.12.11 13:53, Michael D. Berger (m.d.berger at ieee.org) wrote:
> 
> > 
> > [...]
> > > 
> > > Hmm? You should usually consume all fds you get passed. 
> And if you 
> > > cannot handle more than one, then exit quickly with an error 
> > > message. And if any of the fds is invalid, then print an error 
> > > message and leave, too.
> > > 
> > > This is what I'd usually use:
> > > 
> > > 
> > > int fd, n;
> > > 
> > > n = sd_listen_fds();
> > > if (n < 0)  {
> > >         fprintf(stderr, "sd_listen_fds(): %s\n", strerror(-n));
> > >         exit(1);
> > > }
> > > 
> > > for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + 
> n; fd ++) {
> > >         if (sd_is_socket_inet(fd, ...) <= 0) {
> > >                 fprintf(stderr, "Invalid socket passed.\n");
> > >                 exit(1);
> > >         }
> > > 
> > >         /* do something with the fd... */ }
> > > 
> > > (This is for the generic case where the service can 
> handle more than 
> > > one fd. If you can handle ony one, then check whether n 
> == 1 and if 
> > > it isn't exit saying you can't deal with more than one fd.)
> > > 
> > > Lennart
> > > 
> > 
> > What you say is clear, but I am perplexed by the fact that 
> in a case 
> > where there will be one handle, that handle will always be 
> 3.  How do 
> > we know that 3 is not being used by something else?  I thought that 
> > the system has to choose a handle that is available.
> 
> As Zbigniew already mentioned systemd as the process which 
> spawns yours has full control on which fds to pass you. It 
> will guarantee that 0, 1,
> 2 are connected to a suitable stdin, stdout, stderr 
> (/dev/null, resp. syslog by default these days), and then 
> starting with fd 3 all sockets used for socket activation. No 
> other fds will be passed to your process.
> 
> In fact, one of the big advantages of systemd here is that it 
> executes all processes in a clearly defined, reset execution 
> environment which services can rely on, very much unlike 
> classic SysV where the fds passed and the process context 
> properties set are dependent on the shell or service that 
> invoked another service, and where "leaked" fds and settings 
> are a frequent problem.
> 
> Lennart
> 
MyServer is a multi-threaded daemon written in C++ that has been
running reliably for years.  It adapted well to MyServer.service
with Type=simple . I am thinking of creating a MyServer.socket .
Read and write are non-blocking, and are regulated by pselect() .

Now MyServer has two listeners, each running in its own thread.
Now with systemd, I am guessing that this would be a good sequence.

 1. Listener A receives a hit.
 2. MyServer starts and runs sd_listen_fds()in its starting thread.
 3. sd_listen_fds() returns 1.  Anything else (for example, 2) is an error.
 4. The starting thread creates threads ListenA and ListenB, passing them
    the receiving IPaddr.
 5. ListenA determines it is the one. It does NOT run listen().  Since
    the hit occurred before MyDaemon was started, there is no signal
    from pselect() .
 6. ListenA runs accept() and gets a handle for a new socket.
 7. ListenA registers with the pselect (don't worry about the details)
    to wait for another hit.
 8. ListenB determines it is not the one.
 9. ListenB registers with pselect to wait for a hit.
10. All subsequent new connections in both listeners are processed
    by listen() until --
11. When all connections disconnect, MyServer exits. 

So what do you think?

Thanks,
Mike.
--
Michael D. Berger
m.d.berger at ieee.org
http://www.rosemike.net/




More information about the systemd-devel mailing list