April 07, 2014
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");
}
April 07, 2014
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.