Socket disconnect


#1

I'm posting it here, seems to affect my CentOS 7 x64 install but the Mac works fine... A little background...

 

Basically what I want to do is start a timer on an Interprocess connection, when the timer fires and no valid communication has happened(its not a proper Interprocess client), disconnect.  I’m doing this to stop script hackers from holding onto a socket..but i’m also pinging the client periodically from the server connection and want to call disconnect if the client doesn’t respond as well… (power failure shutdown for instance)

To replicate my problem i’ve just been telneting onto the port that the server is running on(8081), now the important bit, type 1 then carriage return. (has to be 5 or less characters not including the cr/lf to be less than the maxBytesToRead). A straight telnet with no data entered disconnects properly.

On linux, I get this...

JUCE Assertion failure in juce_Thread.cpp:200


Thread 4 (Thread 0x7fffed09b700 (LWP 14747)):

#0  0x00007ffff6fd225d in read () from /lib64/libpthread.so.0

#1  0x000000000068feef in juce::SocketHelpers::readSocket (handle=16, destBuffer=0x7fffed09acc0, maxBytesToRead=8, connected=@0x7fffe0000920: false, 

    blockUntilSpecifiedAmountHasArrived=true) at ../../../../juce/modules/juce_core/network/juce_Socket.cpp:107

#2  0x0000000000690723 in juce::StreamingSocket::read (this=0x7fffe0000910, destBuffer=0x7fffed09acc0, maxBytesToRead=8, 

    blockUntilSpecifiedAmountHasArrived=true) at ../../../../juce/modules/juce_core/network/juce_Socket.cpp:306

#3  0x0000000000719fe0 in juce::InterprocessConnection::readNextMessageInt (this=0x7fffe0000930)

    at ../../../../juce/modules/juce_events/interprocess/juce_InterprocessConnection.cpp:281

#4  0x000000000071a314 in juce::InterprocessConnection::runThread (this=0x7fffe0000930)

    at ../../../../juce/modules/juce_events/interprocess/juce_InterprocessConnection.cpp:362

#5  0x000000000071cd67 in juce::InterprocessConnection::ConnectionThread::run (this=0x7fffe0000a70)

    at ../../../../juce/modules/juce_events/interprocess/juce_InterprocessConnection.cpp:29

#6  0x000000000069f87f in juce::Thread::threadEntryPoint (this=0x7fffe0000a70) at ../../../../juce/modules/juce_core/threads/juce_Thread.cpp:101

#7  0x000000000069f8ec in juce::juce_threadEntryPoint (userData=0x7fffe0000a70) at ../../../../juce/modules/juce_core/threads/juce_Thread.cpp:113

#8  0x00000000006bb178 in juce::threadEntryProc (userData=0x7fffe0000a70) at ../../../../juce/modules/juce_core/native/juce_posix_SharedCode.h:861

#9  0x00007ffff6fcbdf3 in start_thread () from /lib64/libpthread.so.0

#10 0x00007ffff399701d in clone () from /lib64/libc.so.6



Thread 1 (Thread 0x7ffff7fd3880 (LWP 14741)):

#0  0x00007ffff38d68b7 in kill () from /lib64/libc.so.6

#1  0x000000000069fc28 in juce::Thread::stopThread (this=0x7fffe0000a70, timeOutMilliseconds=4000)

    at ../../../../juce/modules/juce_core/threads/juce_Thread.cpp:200

#2  0x00000000007197b1 in juce::InterprocessConnection::disconnect (this=0x7fffe0000930)

    at ../../../../juce/modules/juce_events/interprocess/juce_InterprocessConnection.cpp:121

#3  0x0000000000595653 in SMServerConnection::timerCallback (this=0x7fffe0000930) at ../../../JUCE_MiniMiner/core/SMServerConnection.cpp:108

#4  0x000000000071c64b in juce::Timer::TimerThread::callTimers (this=0x7fffe0001590) at ../../../../juce/modules/juce_events/timers/juce_Timer.cpp:127

#5  0x000000000071c8ad in juce::Timer::TimerThread::CallTimersMessage::messageCallback (this=0x7fffd40008e0)

    at ../../../../juce/modules/juce_events/timers/juce_Timer.cpp:198

#6  0x000000000071e1a7 in juce::InternalMessageQueue::dispatchNextInternalMessage (this=0x1036480)

    at ../../../../juce/modules/juce_events/native/juce_linux_Messaging.cpp:202

#7  0x000000000071dbdf in juce::InternalMessageQueue::dispatchNextEvent (this=0x1036480)

    at ../../../../juce/modules/juce_events/native/juce_linux_Messaging.cpp:93

#8  0x000000000071b713 in juce::MessageManager::dispatchNextMessageOnSystemQueue (returnIfNoPendingMessages=true)

    at ../../../../juce/modules/juce_events/native/juce_linux_Messaging.cpp:388

#9  0x0000000000717a33 in juce::MessageManager::runDispatchLoopUntil (this=0x1036420, millisecondsToRunFor=200)

    at ../../../../juce/modules/juce_events/messages/juce_MessageManager.cpp:99

#10 0x0000000000542238 in main (argc=1, argv=0x7fffffffe448) at ../../Source/Main.cpp:112

Which makes it seem like the socket thread is stuck on read.  I have confirmed ::close is being called properly, but that doesn't appear to be enough.

 

The fix is to patch the Socket close code so...

 if (handle != -1)

{

::shutdown(handle,SHUT_RDWR);        

        ::close (handle);

}   

When this is done, its enough to make the ::read call bail out(as it does on mac with a simple close).

Does anyone know of any issues with this fix?  I've googled some source code and quite a few libraries are doing it this way.

 

https://github.com/mono/mono/blob/master/mono/io-layer/sockets.c

http://opensource.apple.com/source/libsecurity_utilities/libsecurity_utilities-24/lib/ip++.cpp?txt

http://svn.apache.org/repos/asf/activemq/tags/activemq-4.0/cms/activemqcms/src/activemq/io/Socket.cpp

http://poco.googlecode.com/svn/trunk/Net/src/SocketImpl.cpp

https://git.fedorahosted.org/cgit/conga.git/plain/ricci/common/Socket.cpp

 

(The mono comment seems applicable to me!  

/* Shutdown the socket for reading, to interrupt any potential
* receives that may be blocking for data. See bug 75705.
*/

Interprocess is waiting for its 8 bytes of magic header, I send 3 bytes when I telnet...)