Re: Process.exec() problem - more details

Peter Lovell <[email protected]> Fri, 15 Jul 2005 18:23:52 -0400
Newsgroups gmane.comp.java.vm.sablevm.devel
Message-ID <[email protected]>
Hi all,
I have been digging into this more extensively, especially today.

 From what I can see, the root cause seems to be a failure in the  
wait/notify process in and around ProcessThread.run and  
Process.waitFor in VMProcess.java

What I see is that  a child process is created (spawn, nativeSpawn  
etc) and runs to completion. It is reaped by nativeReap (called from  
ProcessThread.run)  and then the termination activity is done. This  
saves exitValue in the process object, sets the state to TERMINATED  
and calls notify() for it.

The main java code has called waitFor() and is waiting for process  
termination, with the precise timing of these actions being somewhat  
unpredictable due to cpu load etc. But in some cases the waiter (main  
thread) never seems to resume. I can't quite pinpoint why, but this  
is what is happening. The visible effect is that the main-line code  
which called waitFor() to wait for process termination just never  
executes again.

I am not sure what is a good way to try to find the root cause here.  
It's obviously timing-sensitive so I've been debugging with printf  
and friends, especially since it's not very frequent.

I don't really want to get into thinlocks and fatlocks  (are there  
anorexic and obese ones too?) as I'm not really sure of what's  
happening there. I realize that I have a sort-of-reproducible case  
and I'm happy to try to track the problem down, but I need some  
advice on how best to do it.

Just for info, the test cases today are on Mac OS X using dual cpu.  
The problem occurs sometime within about 600 tries.

Thanks.....Peter







On Jul 11, 2005, at 1:49 PM, Peter Lovell wrote:

> Hi folks,
> I'm having a problem which I believe to be with exec'ing a process  
> and wonder if someone might be able to help. Sometimes another set  
> of eyeballs is all it takes.
>
> The problem is an intermittent failure which appears to be a  
> deadlock somewhere. The frequency is about two or three times every  
> hundred tries. I've appended the java code below (small extract)  
> and I can't see any specific problem with it - after all it works - 
> most- of the time. Problem is that the call is made to this method  
> and the process then remains asleep. In a few instances, the  
> process list shows a zombie process...
> 31747 pts/49   Z+     0:00 [who] <defunct>
>
> A few items of background - I see this problem on Linux (SuSE 9.1,  
> kernel 2.6.4) and Mac OS X (10.4.1, dual processor G5). There had  
> been a couple of instances on Linux 2.4.20 SuSE 8.2 but that does  
> not seem to be happening now (more testing needed). Testing on Sun  
> Java has never produced a failure, even in days of testing. The  
> sable+classpath version is 1.1.8 but comparison of that code with  
> current doesn't seem to show any substantial difference in this  
> area [I've been trying today to get latest code but sablevm.org  
> site is down, unfortunately]
>
> I'm suspecting a subtle timing issue within classpath as the root  
> cause. All suggestions gratefully accepted.
>
> Thanks.....Peter
>
>
>
>
>    public String[] getConnectedUsers()
>    {
>       int              count = 0;
>       int              status = -1;
>       String           s;
>       Runtime          rt;
>       Process          p;
>       ArrayList        return_data = new ArrayList(32);
>       String[]         cu = new String[0];
>
>       try {
>          rt = java.lang.Runtime.getRuntime();
>          p = rt.exec(("who"));
>          status = p.waitFor();
>          if (status != 0){
>             System.err.println("WARNING:  'who' failed,  
> getConnectedUsers failed");
>             return cu;
>          }
>          InputStream ain = p.getInputStream();
>          if ( ain == null ){
>             System.err.println("WARNING:  'who' missing,  
> getConnectedUsers failed");
>             return cu;
>          }
>          BufferedReader in = new BufferedReader( new  
> InputStreamReader ( ain ) );
>          if ( in == null ) {
>             System.err.print("getConnectedUsers: in is null -  
> command must have failed, status = ");
>             System.err.println(status);
>          } else {
>             while ( (s = in.readLine()) != null) {
>                if ( (s.length() < 1) || (s.substring(0,1).equals 
> ("#")))
>                   continue;    //ignore zero-length line (if any)  
> and the user count line
>                return_data.add(s.substring(0, 9).trim());
>             }
>             cu = (String[])return_data.toArray(new String 
> [return_data.size()]);
>          }
>       }
>       catch (InterruptedException ie) {
>          System.err.println("InterruptedException caught");
>       }
>       catch (IOException ioe) {
>          System.err.println("i/o error");
>       }
>       return cu;
>    }
>
>