xiaoshua / junixsocket

Automatically exported from code.google.com/p/junixsocket
0 stars 0 forks source link

Cancelling accept() requests #6

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
Hi.

Is it possible to cancel the waiting accept() request (by interrupting the 
Thread)?

If not, this would be a valuable addition.

Thanks!

Original issue reported on code.google.com by Stas.Os...@gmail.com on 19 Jan 2010 at 12:29

GoogleCodeExporter commented 9 years ago
Could you please give a test case that works with simple Java sockets but does 
not with junixsocket?

If the feature you wish is not supported by simple Java sockets I would 
actually not implement it directly in 
junixsocket.

Best,
Christian

Original comment by ckkohl79 on 19 Jan 2010 at 7:47

GoogleCodeExporter commented 9 years ago
Do you mean that junixsocket supports cancellation out of box?

I checked out the accept() function source code, and there don't seem to be any
thread cancel spot there.

Original comment by Stas.Os...@gmail.com on 19 Jan 2010 at 8:00

GoogleCodeExporter commented 9 years ago
junixsocket currently only supports blocking IO.

See
http://forums.sun.com/thread.jspa?threadID=153781&tstart=139469
http://stackoverflow.com/questions/1510403/how-unblock-thread-blocked-on-servers
ocket-accept
for a discussion on how to cancel ServerSockets from other Threads.

Original comment by ckkohl79 on 19 Jan 2010 at 8:06

GoogleCodeExporter commented 9 years ago
Hi.

Thanks for the links, I quite familiar with the both interrupt and socket 
closing
techniques.

Question is, if the interrupting/closing is working reliably with junixsocket?
Are there any dangers of hanging or crashing?

Thanks.

Original comment by Stas.Os...@gmail.com on 20 Jan 2010 at 7:42

GoogleCodeExporter commented 9 years ago
As junixsocket most of the time just forwards the Java requests to system 
calls, I expect that junixsocket 
behaves just as other C libraries.

Right now, we are missing an exhaustive set of test cases, so I cannot tell for 
sure that there are no "dangers". 
The best way to see is to write a Junit test case. Could you please provide a 
junit class? If you can trigger a 
problem, we can fix it. If the test passes without errors/warnings, still we 
can include the test case to the 
junixsocket codebase.

Original comment by ckkohl79 on 20 Jan 2010 at 7:55

GoogleCodeExporter commented 9 years ago
Hi.

I will try to make such a test - can you tell what C function is called on 
accept()
Java call?

Regards.

Original comment by Stas.Os...@gmail.com on 22 Jan 2010 at 9:11

GoogleCodeExporter commented 9 years ago
Hello there,

I am having this very same issue. With inet sockets accept() raises an 
exception if 
the socket is closed by any other thread. It does not happen with sockets 
provided by 
junixsockets and the test fails because the thread executing accept() never 
joins. 
Please see attached file for example.

The output of the result is:

0    [TestNGInvoker-capabilityUnix()] INFO  
com.sysmech.lab.accept.CapabilityTest  - 
Entering UNIX test
10   [TestNGInvoker-capabilityUnix()] INFO  
com.sysmech.lab.accept.CapabilityTest$Server  - Starting server
10   [TestNGInvoker-capabilityUnix()] INFO  
com.sysmech.lab.accept.CapabilityTest$Server  - Waiting for the server to start 
up
11   [Thread-1] INFO  com.sysmech.lab.accept.CapabilityTest$Server  - Accepting 
connections
1011 [TestNGInvoker-capabilityUnix()] INFO  
com.sysmech.lab.accept.CapabilityTest$Server  - Stopping server
1011 [TestNGInvoker-capabilityUnix()] INFO  
com.sysmech.lab.accept.CapabilityTest$Server  - Joining server thread
3010 [TestNGInvoker-capabilityInet()] INFO  
com.sysmech.lab.accept.CapabilityTest  - 
Entering INET test
3010 [TestNGInvoker-capabilityInet()] INFO  
com.sysmech.lab.accept.CapabilityTest$Server  - Starting server
3010 [TestNGInvoker-capabilityInet()] INFO  
com.sysmech.lab.accept.CapabilityTest$Server  - Waiting for the server to start 
up
3011 [Thread-2] INFO  com.sysmech.lab.accept.CapabilityTest$Server  - Accepting 
connections
4011 [TestNGInvoker-capabilityInet()] INFO  
com.sysmech.lab.accept.CapabilityTest$Server  - Stopping server
4011 [TestNGInvoker-capabilityInet()] INFO  
com.sysmech.lab.accept.CapabilityTest$Server  - Joining server thread
4011 [Thread-2] ERROR com.sysmech.lab.accept.CapabilityTest$Server  - 
java.net.SocketException: Socket closed
4011 [TestNGInvoker-capabilityInet()] INFO  
com.sysmech.lab.accept.CapabilityTest$Server  - Server stopped
4011 [TestNGInvoker-capabilityInet()] INFO  
com.sysmech.lab.accept.CapabilityTest  - 
Leaving INET test
Tests run: 2, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 4.326 sec <<< 
FAILURE!

Regards,
Enrique.

Original comment by enrique....@gmail.com on 5 Feb 2010 at 5:17

Attachments:

GoogleCodeExporter commented 9 years ago
Hello again,

I've figured out a work around for this. I've modified the native code to 
perform a 
select() on the server socket with a timeout of 200 milliseconds. When time 
expires, 
if the socket is still opened, select() returns 0 and we call select() again. 
If the 
socket has been closed by another thread, select() returns -1 and we throw a 
AFUNIXSocketException with the same message as standard Java Sockets. 

If select() returns a valid value, we then proceed to do the accept. Not the 
best but 
good enough for me. 

Please find attached the patch file.

BTW: I have also ported it to a Tru64 box. The patch file also contains those 
changes.

Regards,
Enrique.

Original comment by enrique....@gmail.com on 11 Feb 2010 at 6:01

Attachments:

GoogleCodeExporter commented 9 years ago
Hi.

Any chance to get an updated version of Junix with this fix?

Also, a fixed fd's leak as described in another ticket would be nice!

Regards.

Original comment by Stas.Os...@gmail.com on 11 Feb 2010 at 6:49

GoogleCodeExporter commented 9 years ago
Hi.

Any idea how stable is the patch above?

I want to use the cancellation feature, but I'd really like the patch to get 
some
peer review.

Thanks!

Original comment by Stas.Os...@gmail.com on 18 Feb 2010 at 10:08

GoogleCodeExporter commented 9 years ago
Enrique,

could you please retest with the latest version in SVN?

A fix for another issue 
(http://code.google.com/p/junixsocket/issues/detail?id=7)
might have fixed that.

Christian

Original comment by ckkohl79 on 8 Apr 2010 at 7:42

GoogleCodeExporter commented 9 years ago
Enrique,
could you please create a new issue with a separate patch for the Tru64 part?

I have found some references that on Tru64/__osf__ recv and send are actually 
not
working as expected.

As I do not have a Tru64 box, I cannot confirm this. Could you please check
statement: "OSF/1 actually disables recv() and send() in <sys/socket.h>"?
(see 
http://www.cs.kent.edu/~javed/internetbook/programs/TCP-client-server/unp.h )

The workaround there was to redefine recv and send to use recfrom and sendto:

#ifdef  __osf__
#undef  recv
#undef  send
#define recv(a,b,c,d)   recvfrom(a,b,c,d,0,0)
#define send(a,b,c,d)   sendto(a,b,c,d,0,0)
#endif

Cheers,
Christian

Original comment by ckkohl79 on 8 Apr 2010 at 7:52

GoogleCodeExporter commented 9 years ago
Enrique,

I have committed the Tru64/__osf__-related parts of your patch to SVN trunk. 
Please
test and let me know if it works.

We probably still need to modify build.xml and NaiveUnixSocket.java to 
recognize the
Tru64 OS.

What do you get for the os.name and os.arch system properties?

Best,
Christian

PS: Marking this issue as "fixed". Re-open a new ticket if necessary.

Original comment by ckkohl79 on 22 Apr 2010 at 5:34

GoogleCodeExporter commented 9 years ago

Original comment by ckkohl79 on 22 Apr 2010 at 6:01

GoogleCodeExporter commented 9 years ago
I'm confused as to the status of this issue.  I have junixsocket 1.3, and it 
does not break out of accept when the socket is closed, nor do I see any code 
(eg the select loop described in this issue) to enable this.  Can you clarify?  
There needs to be some way to break out of accept, and (unfortunately) closing 
the socket seems to be the de-facto method (from the Sun implementation).

Original comment by tol...@gmail.com on 4 Oct 2010 at 7:40

GoogleCodeExporter commented 9 years ago
(re-opening the issue)

Hi tolmip,

I have added a new testcase to SVN, demonstrating the current behavior. The 
testcase works for me. If the testcase fails on your side, please consider 
rebuilding the native library and double-check that you are using the most 
recent version of junixsocket.

Feel free to submit patches to the testcase if you want to address any other 
kind of behavior.

Best,
Christian

Original comment by ckkohl79 on 4 Oct 2010 at 8:17

GoogleCodeExporter commented 9 years ago
This is the testcase:
http://code.google.com/p/junixsocket/source/browse/trunk/junixsocket/src/test/or
g/newsclub/net/unix/CancelAcceptTest.java

Original comment by ckkohl79 on 4 Oct 2010 at 8:18

GoogleCodeExporter commented 9 years ago
Thank you for the follow-up.  I rebuilt from svn for amd64 and indeed the test 
fails.  I will investigate.

Original comment by tol...@gmail.com on 4 Oct 2010 at 9:53

GoogleCodeExporter commented 9 years ago
Interesting.

I forgot to mention, I tested this on my Mac, running OS X 10.6. I will conduct 
further tests on other platforms.

Cheers,
Christian

Original comment by ckkohl79 on 4 Oct 2010 at 9:57

GoogleCodeExporter commented 9 years ago
amd64 linux I should say.

Original comment by tol...@gmail.com on 4 Oct 2010 at 9:57

GoogleCodeExporter commented 9 years ago
A few things have been confusing me.  There is a copy-n-pasted comment in 
CancelAcceptTest, so I thought setSoTimeout was connected to accept 
cancellation.  I thought this was connected to comment 8, ie, that timeouts 
were being used to make accept cancellable.

But I believe this was all a red herring.  It looks like you expect the OS to 
interrupt accept when the socket is closed.  But this simply isn't the case on 
Linux.  I can't immediately find a reference for this, but here is something 
similar, with select instead of accept: 
http://fixunix.com/unix/84483-select-socket-close.html.  By the way, this 
article points out the need to synchronize all socket operations against close, 
to make sure that the fd hasn't been reused.  It doesn't look like junixsocket 
does this.

I don't know what the right solution is for linux.  Signals are one possibility 
but I don't know about their use in the JNI environment.  Timeouts and polling 
on a closed flag is another, though the overhead and latency could be annoying. 
 Another alternative is to open up a control pipe for each server socket and 
for accept, do a non-blocking accept then select on both the server socket and 
the pipe.  When another thread wants to close the socket, it writes to the 
control pipe to wake up the select.

Original comment by tol...@gmail.com on 4 Oct 2010 at 11:21

GoogleCodeExporter commented 9 years ago
Probably the best way: for close, just set a flag and do a connect; when the 
accept returns, check the flag to see if this connection really means close.

Original comment by tol...@gmail.com on 5 Oct 2010 at 12:17

GoogleCodeExporter commented 9 years ago
Forget my last comment (22), that was totally stupid and I blame the person who 
voiced the idea on the web. :-)  You could not know whether your accept was 
from close or from a real connection.  (At least, I cannot think of a way to 
distinguish them.)  So one of the other approaches is required.

Original comment by tol...@gmail.com on 5 Oct 2010 at 5:27

GoogleCodeExporter commented 9 years ago
Hi tolmip,
w.r.t. comment 21, yes the copy/paste javadoc was misleading, sorry. I have 
committed a clean version to SVN.

Regarding #22/#23, the flag solution is actually not bad. It does not make a 
difference who actually connects at that time (i.e., you do not have to 
distinguish them). Closing a server socket is a hard cut.

You just need to catch the case that somebody else already connected when the 
flag was set to true (because in that case, your second connection attempt will 
fail).

Does that make sense?

Original comment by ckkohl79 on 5 Oct 2010 at 6:16

GoogleCodeExporter commented 9 years ago
It does make a difference to me who actually connects!  If a legitimate 
connection is received, I need to service it.  My goal is a graceful shutdown, 
where all connections received before I close the listening socket run to 
completion.

Original comment by tol...@gmail.com on 5 Oct 2010 at 6:30

GoogleCodeExporter commented 9 years ago
Maybe you're right thought, it may not be possible to provide the guarantee I 
want anyway....

Original comment by tol...@gmail.com on 5 Oct 2010 at 7:08

GoogleCodeExporter commented 9 years ago
Yes, you are surely right in comment 24: when you call close, you should not 
expect anything else to work from then on.  I was looking for more of a "stop 
listening, but let me continue to process the backlog" semantic.  But this is 
not actually possible with sockets.

Original comment by tol...@gmail.com on 6 Oct 2010 at 4:26

GoogleCodeExporter commented 9 years ago
Hi.

Is the issue fixed already on Linux 64-bit?

Original comment by neoitisr...@gmail.com on 31 Oct 2010 at 8:18

GoogleCodeExporter commented 9 years ago
Re #28:

Hi!
Please try the latest version from SVN and tell me if it works for you. There 
are testcases to see whether it's working (see above).

Best,
Christian

Original comment by ckkohl79 on 31 Oct 2010 at 8:21

GoogleCodeExporter commented 9 years ago
Any news on this? Does it now work for you?

Original comment by ckkohl79 on 17 Dec 2010 at 1:29

GoogleCodeExporter commented 9 years ago
I have built from the latest svn trunk. I have tried 32-bit and 64-bit linux. 

Closing the socket does not break out of accept() for me.

I have verified this using CancelAcceptTest, and also in a real world 
application.

Original comment by phils...@gmail.com on 2 Apr 2011 at 8:36

GoogleCodeExporter commented 9 years ago
I pulled latest, built and ran the unit tests, and I see CancelAcceptTest 
failing.  I'm on Debian Linux 64bit.

Original comment by potatopa...@gmail.com on 10 Jun 2011 at 6:04

GoogleCodeExporter commented 9 years ago
Any updates for this issue? I am also running into this on REDHAT 5.5 AS.
2.6.18-274.3.1.el5 #1 SMP Fri Aug 26 18:49:02 EDT 2011 x86_64 x86_64 x86_64 
GNU/Linux 
Thanks.
Sreeni

Original comment by msbhar...@gmail.com on 28 Oct 2011 at 5:53

GoogleCodeExporter commented 9 years ago
Please, any comments?  I am really blocked by this. I want to cancel out of the 
native accept() call.  Its clearly blocked in Native accept method, even after 
the serversocket.close().

   java.lang.Thread.State: RUNNABLE
        at org.newsclub.net.unix.NativeUnixSocket.accept(Native Method)
        at org.newsclub.net.unix.AFUNIXSocketImpl.accept(AFUNIXSocketImpl.java:58)
        at org.newsclub.net.unix.AFUNIXServerSocket.accept(AFUNIXServerSocket.java:104)

Sreeni

Original comment by msbhar...@gmail.com on 28 Oct 2011 at 11:43

GoogleCodeExporter commented 9 years ago
Try with the latest version in SVN, #r116 and let me know if it works for you.

Original comment by ckkohl79 on 20 Feb 2013 at 12:19

GoogleCodeExporter commented 9 years ago

Original comment by ckkohl79 on 20 Feb 2013 at 12:19

GoogleCodeExporter commented 9 years ago
Hi, I am Damien from France.
As I have just encountered this issue, and tried your patch r116, i leave a 
feedback : just works fine.
Thank you.

My env : 
Linux localhost.localdomain 2.6.18-92.el5 #1 SMP Tue Apr 29 13:16:15 EDT 2008 
x86_64 x86_64 x86_64 GNU/Linux

java version "1.6.0_39"
Java(TM) SE Runtime Environment (build 1.6.0_39-b04)
Java HotSpot(TM) Client VM (build 20.14-b01, mixed mode, sharing)

Original comment by damien.g...@gmail.com on 26 Aug 2013 at 10:53

GoogleCodeExporter commented 9 years ago
Issue 24 has been merged into this issue.

Original comment by ckkohl79 on 30 Nov 2014 at 12:33

GoogleCodeExporter commented 9 years ago
Seems to be fixed as per r116. Please reopen if necessary.

Original comment by ckkohl79 on 30 Nov 2014 at 12:36