Hi, This patch is the library fix for a thread deadlock that occurred when libcurl is missing. It is only one half of the fix for the PR, the other is for the testsuite scripts to check that libcurl exists before attempting to run the std.net.curl unittest.
Bootstrapped and tested on x86_64-linux-gnu (-m32) to verify test goes from timed out to just fail. Committed to trunk as r268746. -- Iain ---
diff --git a/libphobos/src/MERGE b/libphobos/src/MERGE index eee413903c0..aef240e0722 100644 --- a/libphobos/src/MERGE +++ b/libphobos/src/MERGE @@ -1,4 +1,4 @@ -d4933a90b1e8446c04d64cd044658f2b33250bd3 +6c9fb28b0f8813d41798202a9d19c6b37ba5da5f The first line of this file holds the git revision number of the last merge done from the dlang/phobos repository. diff --git a/libphobos/src/std/net/curl.d b/libphobos/src/std/net/curl.d index 9d751411705..e3ce527c303 100644 --- a/libphobos/src/std/net/curl.d +++ b/libphobos/src/std/net/curl.d @@ -178,7 +178,7 @@ version (unittest) import std.range; import std.stdio; - import std.socket : Address, INADDR_LOOPBACK, Socket, TcpSocket; + import std.socket : Address, INADDR_LOOPBACK, Socket, SocketShutdown, TcpSocket; private struct TestServer { @@ -192,6 +192,7 @@ version (unittest) private: string _addr; Tid tid; + TcpSocket sock; static void loop(shared TcpSocket listener) { @@ -215,20 +216,34 @@ version (unittest) private TestServer startServer() { + tlsInit = true; auto sock = new TcpSocket; sock.bind(new InternetAddress(INADDR_LOOPBACK, InternetAddress.PORT_ANY)); sock.listen(1); auto addr = sock.localAddress.toString(); auto tid = spawn(&TestServer.loop, cast(shared) sock); - return TestServer(addr, tid); + return TestServer(addr, tid, sock); } + __gshared TestServer server; + bool tlsInit; + private ref TestServer testServer() { - __gshared TestServer server; return initOnce!server(startServer()); } + static ~this() + { + // terminate server from a thread local dtor of the thread that started it, + // because thread_joinall is called before shared module dtors + if (tlsInit && server.sock) + { + server.sock.shutdown(SocketShutdown.RECEIVE); + server.sock.close(); + } + } + private struct Request(T) { string hdrs; @@ -429,7 +444,11 @@ if (isCurlConn!Conn) s.send(httpOK("Hello world")); }); auto fn = std.file.deleteme; - scope (exit) std.file.remove(fn); + scope (exit) + { + if (std.file.exists(fn)) + std.file.remove(fn); + } download(host, fn); assert(std.file.readText(fn) == "Hello world"); } @@ -491,7 +510,11 @@ if (isCurlConn!Conn) foreach (host; [testServer.addr, "http://"~testServer.addr]) { auto fn = std.file.deleteme; - scope (exit) std.file.remove(fn); + scope (exit) + { + if (std.file.exists(fn)) + std.file.remove(fn); + } std.file.write(fn, "upload data\n"); testServer.handle((s) { auto req = s.recvReq;