digitalmars.D - Bug in std.socket
- Graham St Jack (104/104) Apr 14 2009 Forgive my ignorance, but can anyone tell me how to post a ticket for
- Denis Koroskin (2/107) Apr 14 2009 http://d.puremagic.com/issues/enter_bug.cgi
-
Stewart Gordon
(6/8)
Apr 14 2009
- Brad Roberts (7/133) Apr 14 2009 Your code is inherently racy. The client thread could attempt to connec...
- Unknown W. Brackets (7/132) Apr 15 2009 Does waiting for a keypress in the client thread do you any favors?
- Graham St Jack (8/16) Apr 15 2009 Thanks for all the useful suggestions. I'm on the ticket bandwagon at
- Brad Roberts (6/26) Apr 15 2009 I was about to close the ticket as invalid due to buggy reproduction
- Graham St Jack (2/31) Apr 15 2009 Someone else already provided a much simpler test case without bugs.
Forgive my ignorance, but can anyone tell me how to post a ticket for phobos? I want to report a bug in std.socket's TcpSocket.accept() (at least it manifests itself there for me) introduced in D 2.0.27 and still there in 2.0.28. The following code runs to completion in 2.026 and blocks on accept in later compiler versions. import std.socket; import std.stdio; import core.thread; class Server { private { InternetAddress mAddress; Thread mThread; } this(InternetAddress address) { mAddress = address; mThread = new Thread(&run); mThread.name = "server".dup; mThread.start; } void join() { mThread.join; } void run() { try { writefln("server - setting up server socket"); auto listener = new TcpSocket(); listener.bind(mAddress); listener.listen(5); // wait for a connection writefln("server - waiting for a client connection"); auto socket = listener.accept(); writefln("server - got a client connection"); // read some data and write it back writefln("server - reading data from the client"); ubyte[100] data; int qty = socket.receive(data); writefln("server - writing the data back to the client"); socket.send(data[0..qty]); } catch (Exception ex) { writefln("server - server got exception: %s", ex); } // terminate writefln("server - terminating"); } } class Client { private { InternetAddress mAddress; Thread mThread; } this(InternetAddress address) { mAddress = address; mThread = new Thread(&run); mThread.name = "client".dup; mThread.start; } void join() { mThread.join; } void run() { try { // connect writefln("client - connecting to server"); auto socket = new TcpSocket(mAddress); writefln("client - connected to server"); // send and receive some data writefln("client - sending data to server"); ubyte[3] send_data; send_data[0] = 41; send_data[1] = 42; send_data[2] = 43; int qty = socket.send(send_data); assert(qty == send_data.length); writefln("client - receiving data from server"); ubyte[100] receive_data; qty = socket.receive(receive_data); writefln("client - got %s bytes from server", qty); } catch (Exception ex) { writefln("client - client got exception %s", ex); } // terminate writefln("client - terminating"); } } int main(string[] args) { writefln("test starting"); try { InternetAddress address = new InternetAddress("localhost", 12345); Server server = new Server(address); Client client = new Client(address); writefln("joining with server"); server.join; writefln("joining with client"); client.join; writefln("finished"); } catch (Exception ex) { writefln("unexpected exception %s", ex); } return 0; }
Apr 14 2009
On Wed, 15 Apr 2009 01:20:38 +0400, Graham St Jack <graham.stjack internode.on.net> wrote:Forgive my ignorance, but can anyone tell me how to post a ticket for phobos? I want to report a bug in std.socket's TcpSocket.accept() (at least it manifests itself there for me) introduced in D 2.0.27 and still there in 2.0.28. The following code runs to completion in 2.026 and blocks on accept in later compiler versions. import std.socket; import std.stdio; import core.thread; class Server { private { InternetAddress mAddress; Thread mThread; } this(InternetAddress address) { mAddress = address; mThread = new Thread(&run); mThread.name = "server".dup; mThread.start; } void join() { mThread.join; } void run() { try { writefln("server - setting up server socket"); auto listener = new TcpSocket(); listener.bind(mAddress); listener.listen(5); // wait for a connection writefln("server - waiting for a client connection"); auto socket = listener.accept(); writefln("server - got a client connection"); // read some data and write it back writefln("server - reading data from the client"); ubyte[100] data; int qty = socket.receive(data); writefln("server - writing the data back to the client"); socket.send(data[0..qty]); } catch (Exception ex) { writefln("server - server got exception: %s", ex); } // terminate writefln("server - terminating"); } } class Client { private { InternetAddress mAddress; Thread mThread; } this(InternetAddress address) { mAddress = address; mThread = new Thread(&run); mThread.name = "client".dup; mThread.start; } void join() { mThread.join; } void run() { try { // connect writefln("client - connecting to server"); auto socket = new TcpSocket(mAddress); writefln("client - connected to server"); // send and receive some data writefln("client - sending data to server"); ubyte[3] send_data; send_data[0] = 41; send_data[1] = 42; send_data[2] = 43; int qty = socket.send(send_data); assert(qty == send_data.length); writefln("client - receiving data from server"); ubyte[100] receive_data; qty = socket.receive(receive_data); writefln("client - got %s bytes from server", qty); } catch (Exception ex) { writefln("client - client got exception %s", ex); } // terminate writefln("client - terminating"); } } int main(string[] args) { writefln("test starting"); try { InternetAddress address = new InternetAddress("localhost", 12345); Server server = new Server(address); Client client = new Client(address); writefln("joining with server"); server.join; writefln("joining with client"); client.join; writefln("finished"); } catch (Exception ex) { writefln("unexpected exception %s", ex); } return 0; }http://d.puremagic.com/issues/enter_bug.cgi
Apr 14 2009
Graham St Jack wrote:Forgive my ignorance, but can anyone tell me how to post a ticket for phobos?<snip> http://d.puremagic.com/issues/ Once you've set yourself up there, use the "New" link, select "D" and then "Phobos" from the component list. Stewart.
Apr 14 2009
Your code is inherently racy. The client thread could attempt to connect before the server thread has finished the steps prior to accept. Also, there's no second . in the version scheme for DMD, it's just 1.xxx or 2.xxx. Later, Brad On Tue, 14 Apr 2009, Graham St Jack wrote:Forgive my ignorance, but can anyone tell me how to post a ticket for phobos? I want to report a bug in std.socket's TcpSocket.accept() (at least it manifests itself there for me) introduced in D 2.0.27 and still there in 2.0.28. The following code runs to completion in 2.026 and blocks on accept in later compiler versions. import std.socket; import std.stdio; import core.thread; class Server { private { InternetAddress mAddress; Thread mThread; } this(InternetAddress address) { mAddress = address; mThread = new Thread(&run); mThread.name = "server".dup; mThread.start; } void join() { mThread.join; } void run() { try { writefln("server - setting up server socket"); auto listener = new TcpSocket(); listener.bind(mAddress); listener.listen(5); // wait for a connection writefln("server - waiting for a client connection"); auto socket = listener.accept(); writefln("server - got a client connection"); // read some data and write it back writefln("server - reading data from the client"); ubyte[100] data; int qty = socket.receive(data); writefln("server - writing the data back to the client"); socket.send(data[0..qty]); } catch (Exception ex) { writefln("server - server got exception: %s", ex); } // terminate writefln("server - terminating"); } } class Client { private { InternetAddress mAddress; Thread mThread; } this(InternetAddress address) { mAddress = address; mThread = new Thread(&run); mThread.name = "client".dup; mThread.start; } void join() { mThread.join; } void run() { try { // connect writefln("client - connecting to server"); auto socket = new TcpSocket(mAddress); writefln("client - connected to server"); // send and receive some data writefln("client - sending data to server"); ubyte[3] send_data; send_data[0] = 41; send_data[1] = 42; send_data[2] = 43; int qty = socket.send(send_data); assert(qty == send_data.length); writefln("client - receiving data from server"); ubyte[100] receive_data; qty = socket.receive(receive_data); writefln("client - got %s bytes from server", qty); } catch (Exception ex) { writefln("client - client got exception %s", ex); } // terminate writefln("client - terminating"); } } int main(string[] args) { writefln("test starting"); try { InternetAddress address = new InternetAddress("localhost", 12345); Server server = new Server(address); Client client = new Client(address); writefln("joining with server"); server.join; writefln("joining with client"); client.join; writefln("finished"); } catch (Exception ex) { writefln("unexpected exception %s", ex); } return 0; }
Apr 14 2009
Does waiting for a keypress in the client thread do you any favors? Also, you can get some mileage by doing a select() (see SocketSet) on the socket first. This will tell you if you need to accept(), and also allow you to do timeouts. I'm a big fan of non-blocking sockets, you can improve connect() this way too. -[Unknown] Graham St Jack wrote:Forgive my ignorance, but can anyone tell me how to post a ticket for phobos? I want to report a bug in std.socket's TcpSocket.accept() (at least it manifests itself there for me) introduced in D 2.0.27 and still there in 2.0.28. The following code runs to completion in 2.026 and blocks on accept in later compiler versions. import std.socket; import std.stdio; import core.thread; class Server { private { InternetAddress mAddress; Thread mThread; } this(InternetAddress address) { mAddress = address; mThread = new Thread(&run); mThread.name = "server".dup; mThread.start; } void join() { mThread.join; } void run() { try { writefln("server - setting up server socket"); auto listener = new TcpSocket(); listener.bind(mAddress); listener.listen(5); // wait for a connection writefln("server - waiting for a client connection"); auto socket = listener.accept(); writefln("server - got a client connection"); // read some data and write it back writefln("server - reading data from the client"); ubyte[100] data; int qty = socket.receive(data); writefln("server - writing the data back to the client"); socket.send(data[0..qty]); } catch (Exception ex) { writefln("server - server got exception: %s", ex); } // terminate writefln("server - terminating"); } } class Client { private { InternetAddress mAddress; Thread mThread; } this(InternetAddress address) { mAddress = address; mThread = new Thread(&run); mThread.name = "client".dup; mThread.start; } void join() { mThread.join; } void run() { try { // connect writefln("client - connecting to server"); auto socket = new TcpSocket(mAddress); writefln("client - connected to server"); // send and receive some data writefln("client - sending data to server"); ubyte[3] send_data; send_data[0] = 41; send_data[1] = 42; send_data[2] = 43; int qty = socket.send(send_data); assert(qty == send_data.length); writefln("client - receiving data from server"); ubyte[100] receive_data; qty = socket.receive(receive_data); writefln("client - got %s bytes from server", qty); } catch (Exception ex) { writefln("client - client got exception %s", ex); } // terminate writefln("client - terminating"); } } int main(string[] args) { writefln("test starting"); try { InternetAddress address = new InternetAddress("localhost", 12345); Server server = new Server(address); Client client = new Client(address); writefln("joining with server"); server.join; writefln("joining with client"); client.join; writefln("finished"); } catch (Exception ex) { writefln("unexpected exception %s", ex); } return 0; }
Apr 15 2009
On Wed, 15 Apr 2009 00:38:33 -0700, Unknown W. Brackets wrote:Does waiting for a keypress in the client thread do you any favors? Also, you can get some mileage by doing a select() (see SocketSet) on the socket first. This will tell you if you need to accept(), and also allow you to do timeouts. I'm a big fan of non-blocking sockets, you can improve connect() this way too. -[Unknown]Thanks for all the useful suggestions. I'm on the ticket bandwagon at last. I realise that the code I posted was a bit rough (although I missed the race, which is definitely there). It was a heavily cut-down version of something a lot larger that does indeed use select, uses non-blocking I/ O, retries connection attempts, and even uses Fibers. What I wanted was a small and simple test case to attach to the ticket, not something serious.
Apr 15 2009
Graham St Jack wrote:On Wed, 15 Apr 2009 00:38:33 -0700, Unknown W. Brackets wrote:I was about to close the ticket as invalid due to buggy reproduction code. Can you demonstrate the problem with an example app that's _not_ buggy? If so, please attach it to the bug report. Later, BradDoes waiting for a keypress in the client thread do you any favors? Also, you can get some mileage by doing a select() (see SocketSet) on the socket first. This will tell you if you need to accept(), and also allow you to do timeouts. I'm a big fan of non-blocking sockets, you can improve connect() this way too. -[Unknown]Thanks for all the useful suggestions. I'm on the ticket bandwagon at last. I realise that the code I posted was a bit rough (although I missed the race, which is definitely there). It was a heavily cut-down version of something a lot larger that does indeed use select, uses non-blocking I/ O, retries connection attempts, and even uses Fibers. What I wanted was a small and simple test case to attach to the ticket, not something serious.
Apr 15 2009
On Wed, 15 Apr 2009 09:35:45 -0700, Brad Roberts wrote:Graham St Jack wrote:Someone else already provided a much simpler test case without bugs.On Wed, 15 Apr 2009 00:38:33 -0700, Unknown W. Brackets wrote:I was about to close the ticket as invalid due to buggy reproduction code. Can you demonstrate the problem with an example app that's _not_ buggy? If so, please attach it to the bug report. Later, BradDoes waiting for a keypress in the client thread do you any favors? Also, you can get some mileage by doing a select() (see SocketSet) on the socket first. This will tell you if you need to accept(), and also allow you to do timeouts. I'm a big fan of non-blocking sockets, you can improve connect() this way too. -[Unknown]Thanks for all the useful suggestions. I'm on the ticket bandwagon at last. I realise that the code I posted was a bit rough (although I missed the race, which is definitely there). It was a heavily cut-down version of something a lot larger that does indeed use select, uses non-blocking I/ O, retries connection attempts, and even uses Fibers. What I wanted was a small and simple test case to attach to the ticket, not something serious.
Apr 15 2009