Skip to main content

Runtime.exec allows child process to inherit handles

22 replies [Last post]
normanr
Offline
Joined: 2007-08-12
Points: 0

re: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6428742

It's possible to reproduce this bug very easily:

import java.net.*;

public class socktest
{
public static void main(String[] args) throws Exception
{
System.out.println("java.version=" + java.lang.System.getProperty("java.version"));
ServerSocket ss = new ServerSocket(4444);
Runtime.getRuntime().exec(new String[] {"notepad.exe"});
System.in.read();
ss.close();
}
}

if that is compiled and executed, it spawns notepad. Notepad inherits the handle to the socket, so if you try and re-execute the test if fails with "BindException: Address already in use".

This was supposed to be fixed in 6u2b01 and 7b12, but I can reproduce the bug in both 6u2final and 7b17.

Is there a 'better way' to do the exec so that handles are not inherited? Is there any reason why you would ever want to inherit handles through exec?

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
normanr
Offline
Joined: 2007-08-12
Points: 0

Unfortunately PE doesn't show tcp handles held by a process, it can only show a list of tcp sockets that were opened by the process (same as netstat -o). Additionally PE doesn't want to show me a list of tcp connection in Vista (not sure why)

fred34
Offline
Joined: 2004-06-19
Points: 0

[nobr]
> Or weird software/patch installed on the machines I'm
> testing on. All three have the .Net Framework
> installed, and are patched with the latest updates
> available. I managed to ask someone to test on a
> win-xp-sp2 with 1.5.0_06, and the bug does not
> reproduce.

Just tried it 1.5.0_11 and things are working fine.

> I hear you, I've managed to get a non-reproducable
> case this end, so only 3 of 4 machines this end are
> reproducing the bug.

So something on three machines, but not on the 4th of either of mine..Hmm. I don't have .net on any of them, so could be..how do your machines stand with Windows Updates? Both of mine are pretty much upto date, but this doesn't feel right to me...Windows Update doesn't feel like it would be affecting it.

> So it's sounding like there's a strange non-race like
> behaviour occurring some of my test systems.

Are there any other symptoms of anything of the test machines where the bug can be reproduced? Java related or otherwise?

> cool, maybe Netbeans is just waiting on the
> process+children. If you take out the socket code,
> does it behave in the same way?

yes. so this is just netbeans waitiing for everything to close before allowing the ant script to terminate. We can ignore this from here on in.

> the screencast doesn't have useful audio, but I think
> you will see what I mean, the class file was compiled
> using jikes, but as you say, I see the same results
> with the jdk javac.

Is very useful. Thanks for that! What I want to try next, is testing with a couple of different processes, (e.g.not notepad, just in case) and also see if other handles can be held open by notepad. E.g. instead of a socket handle, can a file handle be held open?

normanr
Offline
Joined: 2007-08-12
Points: 0

I've tried 1.5.0_12-b04 on my vista laptop, and it still fails.

I'm guessing that some other something has been installed which is breaking it, but to track it down is going to be a nightmare. Maybe something in the window socket stack? Doesn't sound likely. Something like anti-virus perhaps? Obviously something that digs around in windows' internals too much. (vista didn't have av until today, so can't be av on it's own - can someone test on another vista machine?)

The machine I found the bug on is pretty old, and full of rubbish, so I wasn't surprised when it was causing a non-standard response. But the other xp machine, and the vista machine are pretty much brand new.

okay, netbeans response isn't surprising, not the issue here :-)

Initially I found the bug with explorer, have been testing with notepad, tried calc quickly and it gives the same result.

Maybe dependant on msvc libs? although CreateProcess in in kernel32.dll, socket operations are in Ws2_32.dll which has been updated too many times to count.

fyi: Vista changed the whole network stack around (look for info on windows filtering platform), so it might respond totally differently.

I've tried with file objects, but I couldn't find a way to open the file exclusively, the best I could do was to lock the file once it was open.

normanr
Offline
Joined: 2007-08-12
Points: 0

Here's my lastest testing (on request of Sun's Incident Update mail):

c:>java socktest:
java.version=1.6.0_02
~launched notepad, stays open~

c:>netstat -ano | find "4444"
TCP 0.0.0.0:4444 0.0.0.0:0 LISTENING 5488
TCP [::]:4444 [::]:0 LISTENING 5488

c:>tasklist /fi "pid eq 5488"

Image Name PID Session Name Session# Mem Usage
========================= ======== ================ =========== ============
java.exe 5488 Console 1 11 284 K

~control-C~

c:>netstat -ano | find "4444"
TCP [::]:4444 [::]:0 LISTENING 5488

c:>tasklist /fi "pid eq 5488"
INFO: No tasks are running which match the specified criteria.

~close notepad~

c:>netstat -ano | find "4444"

~no items~

So it looks like the IPv4 socket has it's handles set to non-inherit, but the IPv6 socket's handle are not.

Can anyone confirm a relationship between IPv6 and the bug?

Update: On my Windows XP SP2 machine (IPv6 disabled, but it has the advanced networking pack installed), the IPv6 entry is missing entirely, but the IPv4 entry stays around until notepad is closed.

alanb
Offline
Joined: 2005-08-08
Points: 0

You are right and the only workaround is to disable IPv6. Can you ask your contact in the webbugs team to pass the incident into the bug database? (category java/classes_net).

ndcosta
Offline
Joined: 2004-05-21
Points: 0

This bug has been recorded in the bug database as "6598160 Windows IPv6 Socket implementation doesn't set the handle to not inherit". Will be visible in a few days at http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6598160

ch122065
Offline
Joined: 2006-01-27
Points: 0

Until this bug is fixed you can use OpenJDK 7 on Vista. From b15 onwards the Socket code is using the new dual layer TCP/IP stack on Vista.

normanr
Offline
Joined: 2007-08-12
Points: 0

The machine that the bug primarily affects is XP SP2, so in the mean time I just remember that I need to close all sub-processes (explorer windows) before relaunching the main process. Either that or I make sure I have at least once explorer window open so that the explorer sub-process is short-lived.

alanb
Offline
Joined: 2005-08-08
Points: 0

If you don't care about IPv6 then the simplest workaround is to just disable it by running with:
-Djava.net.preferIPv4Stack=true

normanr
Offline
Joined: 2007-08-12
Points: 0

meh, setting that doesn't help on Windows XP SP2 with 6.02 or 7b17

ch122065
Offline
Joined: 2006-01-27
Points: 0

I just tested a run with "Djava.net.preferIPv4Stack=true" set on the command line on Windows 2003 with IPv6 enabled. I could reproduce the bug without this property set and could not reproduce it with the property set. Also looking at the logic in the native for socket creation code this option should make the bug disappear, in that the IPv6 socket is never created.

One cautionary note is that this option needs to be set on the command line. The reason is that its value is only ever read once by the java networking stack.

normanr
Offline
Joined: 2007-08-12
Points: 0

preferIPv4Stack fixes the bug on my Vista machine, but not on the XP SP2, with IPv6 disabled.

spdenne
Offline
Joined: 2006-02-15
Points: 0

SysInternal's Process Explorer can be used to show the handles being held by each process.

fred34
Offline
Joined: 2004-06-19
Points: 0

and I really should have been able to remember that.......

alanb
Offline
Joined: 2005-08-08
Points: 0

There's something fishy here. Does this happen if you use a port other than 4444?

normanr
Offline
Joined: 2007-08-12
Points: 0

Yea, it works on any port (just checked a bunch of other ports), 4444 was a random choice. I initially discovered the bug using Azureus, which listens on many ports, some user configurable, some not.

normanr
Offline
Joined: 2007-08-12
Points: 0

I retested this with jre 1.6.0_01 and 1.6.0_02 on vista on another machine, compiling using jikes. (just to check it isn't something I have installed on the win xp sp2 machine, compiling with jdk's javac), and it shows the same issues. (just to check 1.6.0_02 == 6u2 right?)

The bug I'm seeing is that unless I close notepad, I can't create another instance of ServerSocket. I expect that if I leave the first java instance open that I will get an exception, but if I close the java test instance, and leave the notepad instance open, then I still get the exception. (fyi, I'm using Enter/Return to exit the java instance)

I'm not 100% sure what you mean about closing the stream, and not closing notepad, causes the java process to stick around.

I think perhaps I should create a screen-cast to show exactly what I'm experiencing would help a lot?

fred34
Offline
Joined: 2004-06-19
Points: 0

> I retested this with jre 1.6.0_01 and 1.6.0_02 on
> vista on another machine, compiling using jikes.
> (just to check it isn't something I have installed on
> the win xp sp2 machine, compiling with jdk's javac),
> and it shows the same issues. (just to check 1.6.0_02
> == 6u2 right?)

Ok, so you know there's nothing wrong with the compiler or OS. That leaves the VM or class library.

> The bug I'm seeing is that unless I close notepad, I
> can't create another instance of ServerSocket.

Umm.. I can. Sorry I just can't reproduce this behaviour.

> I expect that if I leave the first java instance open
> that I will get an exception, but if I close the java
> test instance, and leave the notepad instance open,
> then I still get the exception. (fyi, I'm using
> Enter/Return to exit the java instance)

I'm still not getting this exception, I'm not saying your wrong at this point, but unless there's something else in your machine configuration affecting this (which seems less likely as you've tested across different machines and OSes) I don't think you understand how serversocket's bind to ports.

Let's take it step by step: First, start an instance of socktest. This will create a socket, bind it to 4444 and spawn a notepad. It then sits waiting at the line "System.in.read()" for some input from the console. If you now try to start a second instance of socktest, then the BindException will *correctly* appear, since it is attempting to bind a second server socket to port 4444 which isn't allowed.

Second, in the first instance, press ENTER/Return, this will cause the java process to continue execution beyond the System.in.read() line and execute "ss.close()". This closes the socket (which is what I meant by closing the stream) and of course releases port 4444. At this stage, the first Java process terminates since it has reached the end of it's main method and no other threads are started. The notepad process stays open since it doesn't rely on the java process here.

Third, with notepad from the first instance still running, execute a second instance of socktest, and it will open a second instance of notepad and rebind a serversocket to 4444.

The BindException that occurs is totally correct as far as I can see, I've run loads of tests on this code and it always behaves as it should for me. I don't think the notepad instance has anything to do with the server socket here, since the only way I can trigger the BindException is by executing a second socktest when the first has only just launched thus causing an exception as the second instance is trying to bind a serversocket to a port which is already owned by the first instance.

> I'm not 100% sure what you mean about closing the
> stream, and not closing notepad, causes the java
> process to stick around.

From a command prompt, the prompt returns as soon as i press enter to continue beyond "System.in.read()", irrespective of whether notepad is still runnning. However, in Netbeans, I don't get the build complete message until I close notepad too. Though I've tried running two instances from the console, through netbeans and combinations thereof but can't reproduce what you're experiencing under any conditions.

> I think perhaps I should create a screen-cast to show
> exactly what I'm experiencing would help a lot?

May help.

normanr
Offline
Joined: 2007-08-12
Points: 0

> Ok, so you know there's nothing wrong with the compiler or OS. That leaves the VM or class library.

Or weird software/patch installed on the machines I'm testing on. All three have the .Net Framework installed, and are patched with the latest updates available. I managed to ask someone to test on a win-xp-sp2 with 1.5.0_06, and the bug does not reproduce.

> Umm.. I can. Sorry I just can't reproduce this behaviour.
> I'm still not getting this exception, I'm not saying
> your wrong at this point, but unless there's
> something else in your machine configuration
> affecting this (which seems less likely as you've
> tested across different machines and OSes) I don't
> think you understand how serversocket's bind to
> ports.

I hear you, I've managed to get a non-reproducable case this end, so only 3 of 4 machines this end are reproducing the bug.

> Let's take it step by step: First, start an instance
> of socktest. This will create a socket, bind it to
> 4444 and spawn a notepad. It then sits waiting at the
> line "System.in.read()" for some input from the
> console. If you now try to start a second instance of
> socktest, then the BindException will *correctly*
> appear, since it is attempting to bind a second
> server socket to port 4444 which isn't allowed.

yes, I agree this behaviour is expected.

> Second, in the first instance, press ENTER/Return,
> this will cause the java process to continue
> execution beyond the System.in.read() line and
> execute "ss.close()". This closes the socket (which
> is what I meant by closing the stream) and of course
> releases port 4444. At this stage, the first Java
> process terminates since it has reached the end of
> it's main method and no other threads are started.
> The notepad process stays open since it doesn't rely
> on the java process here.

yep, as it turns out the ss.close() makes very little difference, I was trying to force the socket closed, but it didn't help.

> Third, with notepad from the first instance still
> running, execute a second instance of socktest, and
> it will open a second instance of notepad and rebind
> a serversocket to 4444.

I expect the second copy to launch without an issue, and for there to be two copies of notepad open. For some reason on these three vastly different machines, the notepad instance is 'conflicting' with being able to re-bind to the same port. If I close notepad, then everything works as expected, if I leave it open I get conflicts.

> The BindException that occurs is totally correct as
> far as I can see, I've run loads of tests on this
> code and it always behaves as it should for me. I
> don't think the notepad instance has anything to do
> with the server socket here, since the only way I can
> trigger the BindException is by executing a second
> socktest when the first has only just launched thus
> causing an exception as the second instance is trying
> to bind a serversocket to a port which is already
> owned by the first instance.

So it's sounding like there's a strange non-race like behaviour occurring some of my test systems.

> From a command prompt, the prompt returns as soon as
> i press enter to continue beyond "System.in.read()",
> irrespective of whether notepad is still runnning.
> However, in Netbeans, I don't get the build complete
> message until I close notepad too. Though I've tried
> running two instances from the console, through
> netbeans and combinations thereof but can't reproduce
> what you're experiencing under any conditions.

cool, maybe Netbeans is just waiting on the process+children. If you take out the socket code, does it behave in the same way?

> > I think perhaps I should create a screen-cast to
> > show exactly what I'm experiencing would help a lot?
> May help.

okay, screencast + java + class files are up at http://www.darkskies.za.net/~norman/java/

the screencast doesn't have useful audio, but I think you will see what I mean, the class file was compiled using jikes, but as you say, I see the same results with the jdk javac.

normanr
Offline
Joined: 2007-08-12
Points: 0

> okay, screencast + java + class files are up at http://www.darkskies.za.net/~norman/java/

fyi: I also uploaded a sockautotest, which lists the system properties, and then tries to automatically test to see if the subprocess inherits the socket handle.

alanb
Offline
Joined: 2005-08-08
Points: 0

This didn't duplicate for me either. We did have a problem with NIO channels inheriting sockets into child processes. That was fixed in 6.0u2. The ServerSocket implementation has also created sockets with the correctly flag setting so that the socket is not inherited.

fred34
Offline
Joined: 2004-06-19
Points: 0

Can you go into more detail what the bug is here, because I can't reproduce it on JDK6u2 (Windows XP SP2). I start the program and a server socket is created on 4444 and notepad starts. If i then type a character to system in, the socket closes as expected. If I then try to start another instance of the program, a second notepad is opened and port 4444 is once again bound.

This seems to be the correct behaviour. If two instances are started without typing any input, then the second instance receiving BindException is the correct behaviour since you can't associate two server sockets to listen to the same port under normal circumstances so this is also completely correct.

The only slightly untuitive behaviour I can see is that if the stream is closed and notepad not, then the Java process doesn't terminate, which again is the expected behaviour, since to answer your final question, can be very useful if using Java to launch a console program where you want its input and output to be controlled via Java.