Hi LKML, I have a C/pthreads program with two threads ("main" and "thread"). "thread" calls recvfrom on a connected UDP socket and blocks, waiting for input. "main" then calls shutdown SHUT_RD on the socket. In "thread", recvfrom returns, apparently successfully, returning a zero length string, and setting src_addr to a bogus(?) address family, port, and source address.
Is the above the correct behavior for recvfrom? Here is output from my program. "main" sends "hello\0", then "" (the empty string), then calls shutdown. "thread" receives "hello\0", "", and then finally receives an empty string that was never sent! thread recvfrom: Success rv 6 addrlen 16 fam 2 port 8000 addr 100007f thread recvfrom: Success rv 0 addrlen 16 fam 2 port 8000 addr 100007f main shutdown: Success rv 0 thread recvfrom: Success rv 0 addrlen 16 fam 59060 port 44237 addr deaadef0 The source code (2k) for the porgram is attached. I'm running Ubuntu 13.04, kernel 3.8.0-19-generic #30-Ubuntu, on 32-bit i686. For reference, this June 2000 LKML thread discusses calling close in a similar situation. http://www.gossamer-threads.com/lists/linux/kernel/144379 Please CC me if you have questions, otherwise I'll try to watch for answers in the list archives. Thanks! -mpb
#include <netinet/in.h> #include <pthread.h> #include <stdio.h> #include <sys/socket.h> #include <sys/types.h> struct sockaddr_in addr_0, addr_1, addr_2 ; int fd0, fd1, rv0, rv1, addrlen; char buf_0[1024], buf_1[1024]; pthread_t thread; void* thread_rv; void* thread_main (void* arg) { int i; for ( i=0; i<3; i++ ) { addr_2.sin_family = 0; addr_2.sin_port = 0; addr_2.sin_addr.s_addr = 0; addrlen = sizeof addr_2; rv1 = recvfrom ( fd1, buf_0, sizeof buf_0, 0, (struct sockaddr*) &addr_2, &addrlen ); int fam = addr_2.sin_family; int port = addr_2.sin_port; int addr = addr_2.sin_addr.s_addr; printf ("\n"); perror ("thread recvfrom"); printf ( " rv %d addrlen %d fam %d port %d addr %x\n", rv1, addrlen, fam, ntohs (port), addr ); ;;; } return NULL; } void main_main () { send ( fd0, "hello", 6, 0); send ( fd0, "", 0, 0); usleep (100000); rv0 = shutdown ( fd1, SHUT_RD ); printf ("\n"); perror ("main shutdown"); printf (" %d\n", rv0) ;;; } int main () { addr_0.sin_family = AF_INET; addr_0.sin_port = htons (8000); inet_pton ( AF_INET, "127.0.0.1", &addr_0.sin_addr ); addr_1.sin_family = AF_INET; addr_1.sin_port = htons (8001); inet_pton ( AF_INET, "127.0.0.1", &addr_1.sin_addr ); fd0 = socket ( AF_INET, SOCK_DGRAM, 0 ); bind ( fd0, (struct sockaddr*) &addr_0, sizeof addr_0 ); connect ( fd0, (struct sockaddr*) &addr_1, sizeof addr_1 ); fd1 = socket ( AF_INET, SOCK_DGRAM, 0 ); bind ( fd1, (struct sockaddr*) &addr_1, sizeof addr_1 ); connect ( fd1, (struct sockaddr*) &addr_0, sizeof addr_0 ); pthread_create ( &thread, NULL, thread_main, NULL ); main_main (); pthread_join ( thread, &thread_rv ); return 0; }