• Florian Zumbiehl's avatar
    UNIX: EOF on non-blocking SOCK_SEQPACKET · 5b5581b7
    Florian Zumbiehl authored
    [UNIX]: EOF on non-blocking SOCK_SEQPACKET
    
    [ Upstream commit: 0a112258 ]
    
    I am not absolutely sure whether this actually is a bug (as in: I've got
    no clue what the standards say or what other implementations do), but at
    least I was pretty surprised when I noticed that a recv() on a
    non-blocking unix domain socket of type SOCK_SEQPACKET (which is connection
    oriented, after all) where the remote end has closed the connection
    returned -1 (EAGAIN) rather than 0 to indicate end of file.
    
    This is a test case:
    
    | #include <sys/types.h>
    | #include <unistd.h>
    | #include <sys/socket.h>
    | #include <sys/un.h>
    | #include <fcntl.h>
    | #include <string.h>
    | #include <stdlib.h>
    |
    | int main(){
    | 	int sock;
    | 	struct sockaddr_un addr;
    | 	char buf[4096];
    | 	int pfds[2];
    |
    | 	pipe(pfds);
    | 	sock=socket(PF_UNIX,SOCK_SEQPACKET,0);
    | 	addr.sun_family=AF_UNIX;
    | 	strcpy(addr.sun_path,"/tmp/foobar_testsock");
    | 	bind(sock,(struct sockaddr *)&addr,sizeof(addr));
    | 	listen(sock,1);
    | 	if(fork()){
    | 		close(sock);
    | 		sock=socket(PF_UNIX,SOCK_SEQPACKET,0);
    | 		connect(sock,(struct sockaddr *)&addr,sizeof(addr));
    | 		fcntl(sock,F_SETFL,fcntl(sock,F_GETFL)|O_NONBLOCK);
    | 		close(pfds[1]);
    | 		read(pfds[0],buf,sizeof(buf));
    | 		recv(sock,buf,sizeof(buf),0); // <-- this one
    | 	}else accept(sock,NULL,NULL);
    | 	exit(0);
    | }
    
    If you try it, make sure /tmp/foobar_testsock doesn't exist.
    
    The marked recv() returns -1 (EAGAIN) on 2.6.23.9. Below you find a
    patch that fixes that.
    Signed-off-by: default avatarFlorian Zumbiehl <florz@florz.de>
    Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
    Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
    5b5581b7
af_unix.c 49 KB