Dear reader(s),
In conclusion of a previous post, I'd like to submit a bug report.
On Windows 7 Ultimate 64 bit using the Visual Studio 2013 (v120) toolset, creating a socket listener on another thread results in Failure every time. This may cause undefined behaviour from accepting a client which can never receive data to returning a NULL client.
I've produced a stable code that creates this problem effortlessly consistently.
As suggested in another post, I've produced this code into a newly generated project using the Introjucer.
This is the only code used and is placed in Main.cpp.
I am using:
Latest release build (Juce version 3.2.0) [I've checked git repository on issues and commits, no changes to the streamingsocket past 3 weeks]
Windows 7 Ultimate SP1 64-bit.
Visual Studio 2013 (v120) toolset for compiling.
Can anyone else verify?
#include "../JuceLibraryCode/JuceHeader.h" class ListenerTest : public juce::Thread { public: ListenerTest(void); ~ListenerTest(void); void run(void); void start(void); private: juce::StreamingSocket* listener; }; ListenerTest::ListenerTest(void) : juce::Thread("LISTENER"), listener(NULL) { } ListenerTest::~ListenerTest(void) { delete listener; listener = NULL; } void ListenerTest::start(void) { listener = new juce::StreamingSocket(); std::cout << "Listener opening success: " << listener->createListener(2300, "") << std::endl; } void ListenerTest::run(void) { while (!threadShouldExit()) { if (listener->waitUntilReady(true, 10) == 1) { juce::StreamingSocket* s = listener->waitForNextConnection(); if (s != NULL) { std::cout << "isConnected: " << s->isConnected() << std::endl; std::cout << "isLocal: " << s->isLocal() << std::endl; std::cout << "Adress: " << s->getHostName() << std::endl; std::cout << "Bound port: " << s->getBoundPort() << std::endl; std::cout << "Port: " << s->getPort() << std::endl; std::cout << s->waitUntilReady(false, 500) << std::endl; std::cout << s->waitUntilReady(true, 500) << std::endl; s->close(); delete s; s = NULL; } else { std::cout << "Invalid connection.." << std::endl; } } else { Thread::yield(); } } listener->close(); delete listener; listener = NULL; } //============================================================================== int main (int argc, char* argv[]) { ListenerTest* test = new ListenerTest(); //This code cannot be run within juce::Thread:run for it will never start listening! test->start();//Start listener using local (main) thread. //create a socket to satisfy listener WaitForNewConnection juce::StreamingSocket* client = new juce::StreamingSocket(); if (client->connect("192.168.1.25", 2300)) { std::cout << "connected" << std::endl; } //test->run();//local (main) thread test->startThread();//separate thread Thread::sleep(4000); client->close(); delete client; client = NULL; test->stopThread(1000); delete test; test = NULL; return 0; }
I would like to know since I am heavily relying on TCP sockets in a project I am involved in which has some higher priority.
PS: I did some more testing and read more upon the winsock API. Now I want to clarify that the original issue at hand for reading on an incoming socket was a mistake on my part. WaitUntilReady(true) only returns 1 when data is in the buffer.
However, the listener can still not be started from another thread and I'd like to know why.
Edit:
Ultimately it came down to a thread being locked due to mutex. I found no notable problems after solving this issue.