pkelsey / libuinet

a library version of FreeBSD's TCP/IP stack plus extras
750 stars 198 forks source link

API for accept4 #7

Open petergsnm opened 10 years ago

petergsnm commented 10 years ago

Can the libuinet expose an API for accept4. I think accept4 is supported in the FreeBSD version which libuinet uses. If an API could be provided, it would be great help for the application to use that.

http://www.freebsd.org/cgi/man.cgi?query=accept&sektion=2

pkelsey commented 10 years ago

I don't think any of the functional or performance reasons that accept4() exists are present when using libuinet.

Consider the case of setting O_NONBLOCK on the new socket. With libuinet, the non-blocking property of the new socket is inherited from the listen socket (normal FreeBSD stack behavior), so this use of accept4() could only be meaningful in cases where you wanted the new socket to have a different blocking configuration than the listen socket. With libuinet, you can change the blocking configuration of the new socket with a single, regular function call following the accept, so even if this was the desired use, I don't see this as a motivation for adding an API point. When using sockets with the kernel stack, configuring O_NONBLOCK after accept() requires two fcntl() system calls, so there would be a more significant savings in using accept4(), but with libuinet it would just be a single, regular function call saved.

accept4() also exists to eliminate a race condition that otherwise exists when you want to set the close-on-exec flag on the file descriptor for the new socket. As libuinet isn't emulating file descriptors, close-on-exec isn't a concept that applies to uinet sockets, so this isn't a motivation for adding an accept4() API point either.

accept4() could be added to the libuinet API to 'make porting to libuinet easier'. In this case, it wouldn't make understanding libuinet easier, and it wouldn't make using libuinet correctly and effectively easier, but it would make using libuinet without awareness of some of the key differences between using it versus using a kernel stack easier. To me, that's a net loss.

petergsnm commented 10 years ago

Thank you Patrick for the detailed explanation. It is more clear to me now.

If you could provide me the API which I can use to change the blocking configuration of the new socket that would be great.

pkelsey commented 10 years ago

void uinet_sosetnonblocking(struct uinet_socket *so, unsigned int nonblocking);

If your uinet listen socket is configured to be nonblocking, all sockets that result from an accept on that listen socket will be nonblocking as well via inheritance.