www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Socket.select interrupted system call because of GC

reply Marek Janukowicz <marek janukowicz.net> writes:
I have a program with one thread waiting on Socket.select call and another 
thread doing stuff causing GC to kick in. When this happens, Socket.select 
fails with "Interrupted system call". I found referenced to some old 
discussion and bug, but it seems to be long gone (I output SA_RESTART in my 
program to make sure it is defined). My program is attached below - it is 
happening on DMD 2.063 on Linux.

import std.socket;
import std.stdio;
import core.thread;
import core.sys.posix.signal;

void serverfunc ()
{
  Socket listener = new TcpSocket ();
  listener.bind (new InternetAddress(1234));
  listener.listen(1);
  SocketSet set = new SocketSet( 1 );
  Socket.select( set, null, null );
  writefln( "last error: %s", lastSocketError() );
}

void clientfunc ()
{
  while( true ) new Object();
}

void main ()
{
  writefln( "sa: %d", SA_RESTART );
  (new Thread (&serverfunc)).start();
  (new Thread (&clientfunc)).start();
}

If I disable GC the problem does not occur.

Any idea how to solve this?

-- 
Marek Janukowicz
Aug 02 2013
parent reply dennis luehring <dl.soluz gmx.net> writes:
Am 03.08.2013 08:38, schrieb Marek Janukowicz:
 void main ()
 {
    writefln( "sa: %d", SA_RESTART );
    (new Thread (&serverfunc)).start();
    (new Thread (&clientfunc)).start();
 }
i have no idea to your main problem but firing threads without any join on the threads in your main program seems very wrong to me - its like allocating memory and let system kill process handle the zombies
Aug 03 2013
parent reply Marek Janukowicz <marek janukowicz.net> writes:
dennis luehring wrote:

 Am 03.08.2013 08:38, schrieb Marek Janukowicz:
 void main ()
 {
    writefln( "sa: %d", SA_RESTART );
    (new Thread (&serverfunc)).start();
    (new Thread (&clientfunc)).start();
 }
i have no idea to your main problem but firing threads without any join on the threads in your main program seems very wrong to me - its like allocating memory and let system kill process handle the zombies
This is of course *not* my entire program (and in fact I made the whole snippet up just to showcase the problem). While I understand your concern it doesn't really make sense to use this piece of code for anything but reproducing the issue at hand. -- Marek Janukowicz
Aug 03 2013
parent reply dennis luehring <dl.soluz gmx.net> writes:
Am 03.08.2013 13:35, schrieb Marek Janukowicz:
 dennis luehring wrote:

 Am 03.08.2013 08:38, schrieb Marek Janukowicz:
 void main ()
 {
    writefln( "sa: %d", SA_RESTART );
    (new Thread (&serverfunc)).start();
    (new Thread (&clientfunc)).start();
 }
i have no idea to your main problem but firing threads without any join on the threads in your main program seems very wrong to me - its like allocating memory and let system kill process handle the zombies
This is of course *not* my entire program (and in fact I made the whole snippet up just to showcase the problem). While I understand your concern it doesn't really make sense to use this piece of code for anything but reproducing the issue at hand.
but you should not reduce your sample down to maybe-incorrect (what it seems for me in this case) - the join wouldn't make your sample to big
Aug 03 2013
parent reply "David Nadlinger" <code klickverbot.at> writes:
On Saturday, 3 August 2013 at 13:19:53 UTC, dennis luehring wrote:
 but you should not reduce your sample down to maybe-incorrect 
 (what it seems for me in this case) - the join wouldn't make 
 your sample to big
The example given is correct, as druntime guarantees that non-daemon threads will run to completion before the program terminates normally (see Thread.isDaemon). David
Aug 03 2013
parent reply Marek Janukowicz <marek janukowicz.net> writes:
David Nadlinger wrote:
 but you should not reduce your sample down to maybe-incorrect
 (what it seems for me in this case) - the join wouldn't make
 your sample to big
The example given is correct, as druntime guarantees that non-daemon threads will run to completion before the program terminates normally (see Thread.isDaemon).
It's really nice to have some chat about the correctness of example code snippets, but can anyone help me with the original issue? :) -- Marek Janukowicz
Aug 03 2013
parent reply "David Nadlinger" <code klickverbot.at> writes:
On Saturday, 3 August 2013 at 15:59:30 UTC, Marek Janukowicz 
wrote:
 It's really nice to have some chat about the correctness of 
 example code
 snippets, but can anyone help me with the original issue? :)
Sorry, apparently I forgot to include the actual content:. ;) Socket.select is an ancient (in D terms) API; you just need to handle the returned error code manually and retry if the errno is actually EINTR resp. its WinSock equivalent. See https://github.com/apache/thrift/blob/master/lib/d/src/thrift/server/tra sport/socket.d#L144 for a production-tested implementation. When I wrote that code, it wasn't possible to do this in a platform-independent way using std.socket (see https://github.com/apache/thrift/blob/master/lib/d/src/thrift/internal/socket.d for the used constants), and I don't think it is now either. David
Aug 03 2013
parent Marek Janukowicz <marek janukowicz.net> writes:
David Nadlinger wrote:
 See
 
https://github.com/apache/thrift/blob/master/lib/d/src/thrift/server/transport/socket.d#L144
 for a production-tested implementation. When I wrote that code,
 it wasn't possible to do this in a platform-independent way using
 std.socket (see
 
https://github.com/apache/thrift/blob/master/lib/d/src/thrift/internal/socket.d
 for the used constants), and I don't think it is now either.
Thanks, I'll use this as my starting point. I'm concerned, however, that even though SA_RESTART option is set the interrupted call is not being restarted, but you need to handle that yourself. -- Marek Janukowicz
Aug 04 2013