www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Socket.receive not popping after socket is closed

reply "Jonathan Marler" <johnnymarler gmail.com> writes:
I ran into a situation where I have a shared UDP socket across 2 
threads.  One thread is blocking on the receive call, and the 
other does some work and then closes the socket.  The problem is 
that the receive call is not popping after the socket is closed.  
I'm fairly certain this is unexpected/incorrect behavior.  I've 
included a small program to demonstrate this:

import std.stdio;
import std.socket;
import std.concurrency;

import core.thread;

__gshared Socket socket;

void receiveDumper()
{
   ubyte[512] receiveBuffer;
   while(true) {
     writeln("[worker] socket.receive(...)"); stdout.flush();
     auto read = socket.receive(receiveBuffer);
     if(read <= 0) {
       if(read < 0) {
         writefln("[worker] socket.receive failed (error=%s '%s')",
	      lastSocketError, socket.getErrorText());
       } else {
         writefln("[worker] Socket closed, stopping thread");
       }
       break;
     }
     writefln("[worker] Got packet");
     stdout.flush();
   }

   writeln("[worker] done"); stdout.flush();
}
void main(string[] args) {
   Address addr = new InternetAddress(InternetAddress.ADDR_ANY, 
12345);

   socket = new Socket(addr.addressFamily, SocketType.DGRAM, 
ProtocolType.UDP);
   socket.bind(addr);

   auto udpListenThread = spawn(&receiveDumper);
   scope(exit) {
     writeln("[main] scope(exit): closing socket..."); 
stdout.flush();
     socket.close();
     writeln("[main] scope(exit): done closing socket"); 
stdout.flush();
   }

   Thread.sleep(dur!("seconds")(1)); // Sleep for a second to let 
the other thread call receive before
                                     // the socket is closed

   writeln("[main] done");
}
Apr 07 2014
parent "Jonathan Marler" <johnnymarler gmail.com> writes:
On Monday, 7 April 2014 at 19:47:07 UTC, Jonathan Marler wrote:
 I ran into a situation where I have a shared UDP socket across 
 2 threads.  One thread is blocking on the receive call, and the 
 other does some work and then closes the socket.  The problem 
 is that the receive call is not popping after the socket is 
 closed.  I'm fairly certain this is unexpected/incorrect 
 behavior.  I've included a small program to demonstrate this:

 import std.stdio;
 import std.socket;
 import std.concurrency;

 import core.thread;

 __gshared Socket socket;

 void receiveDumper()
 {
   ubyte[512] receiveBuffer;
   while(true) {
     writeln("[worker] socket.receive(...)"); stdout.flush();
     auto read = socket.receive(receiveBuffer);
     if(read <= 0) {
       if(read < 0) {
         writefln("[worker] socket.receive failed (error=%s 
 '%s')",
 	      lastSocketError, socket.getErrorText());
       } else {
         writefln("[worker] Socket closed, stopping thread");
       }
       break;
     }
     writefln("[worker] Got packet");
     stdout.flush();
   }

   writeln("[worker] done"); stdout.flush();
 }
 void main(string[] args) {
   Address addr = new InternetAddress(InternetAddress.ADDR_ANY, 
 12345);

   socket = new Socket(addr.addressFamily, SocketType.DGRAM, 
 ProtocolType.UDP);
   socket.bind(addr);

   auto udpListenThread = spawn(&receiveDumper);
   scope(exit) {
     writeln("[main] scope(exit): closing socket..."); 
 stdout.flush();
     socket.close();
     writeln("[main] scope(exit): done closing socket"); 
 stdout.flush();
   }

   Thread.sleep(dur!("seconds")(1)); // Sleep for a second to 
 let the other thread call receive before
                                     // the socket is closed

   writeln("[main] done");
 }

Nevermind, it looks calling the "shutdown" method did the trick.
Apr 07 2014