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.
