Anzeige:
Ergebnis 1 bis 5 von 5

Thema: process.getInputStream() hängt auf merkwürdige Art und Weise

  1. #1
    Registrierter Benutzer
    Registriert seit
    14.03.2007
    Beiträge
    6

    process.getInputStream() hängt auf merkwürdige Art und Weise

    Hallo zusammen,

    ich habe ein völlig merkwürdiges Problem bei dem ich nach einem Tag rumprobieren überhaupt nicht mehr weiterkomme...

    Folgendes:

    - ich verwende das Microsoft-Tool "handle" (eine simple exe) um aus einer java-Applikation heraus zu prüfen
    ob irgendein Prozess auf eine Datei zugreift.

    Eine einfache Testklasse funktioniert auch bestens:

    Code:
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    
    
    public class TestIt {
    
    	public static void main(String[] args){
    
    		String pathToFileHandleTool = "C:\\tmp\\Handle\\handle.exe";
    		String pathToFile = "C:\\tmp\\openSUSE-10.2-GM-i386-CD3.iso";
    		String expectedFileHandleSuccessOutput = "(.*)No matching handles found(.*)";
    		System.out.println("pathToFileHandleTool:" + pathToFileHandleTool);
    		System.out.println("pathToFile: " + pathToFile);
    		System.out.println("expectedFileHandleSuccessOutput: " + expectedFileHandleSuccessOutput);
    		
    		ProcessBuilder builder = null;
    		// check for os
    		if(System.getProperty("os.name").matches("(.*)Windows(.*)")) {
    			System.out.println("we are on windows..");
    		} else {
    			System.out.println("we are on linux..");
    		}
    		builder = new ProcessBuilder( pathToFileHandleTool, pathToFile);
    		Process process = null;
    		String commandOutput = "";
    		String line = null;
    		BufferedReader bufferedReader = null;
    		try {
    			process = builder.start();
    			// read command output
    			bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
    			if(!bufferedReader.ready()) {
    				System.out.println("bufferedReader not ready!");
    			}
    	    	System.out.println("bin vor readline!");
    	    	while((line = bufferedReader.readLine()) != null) {
    	    		commandOutput += line;
                            System.out.println("reading in line....");
    	    	}
    	    	System.out.println("bin nach readline!");
    	    	System.out.println("commandoutput: " + commandOutput);
    			// wait till process has finished
    			process.waitFor();
    		} catch (IOException e) {
    			System.out.println(e.getMessage());
    			e.printStackTrace();
    		}  catch (InterruptedException e) {
    			System.out.println(e.getMessage());
    			e.printStackTrace();		}
    		// check output to assure that no process uses file
    		if(commandOutput.matches(expectedFileHandleSuccessOutput))
    			System.out.println("no other processes accesses file!");
    		else
    			System.out.println("one or more other processes access file!");
    	}
    }
    (Wundert euch nicht wegen sinnlos aussehenden Ausgaben wie "bin vor readline!" usw., Begründung kommt
    später)

    Rufe ich diese Klasse auf und niemand greift auf die Datei "C:\\tmp\\openSUSE-10.2-GM-i386-CD3.iso" zu
    sieht die Ausgabe des Programms so aus:


    Code:
    pathToFileHandleTool:C:\tmp\Handle\handle.exe
    pathToFile: C:\tmp\openSUSE-10.2-GM-i386-CD3.iso
    expectedFileHandleSuccessOutput: (.*)No matching handles found(.*)
    we are on windows..
    bufferedReader not ready!
    bin vor readline!
    reading in line....
    reading in line....
    reading in line....
    reading in line....
    reading in line....
    reading in line....
    bin nach readline!
    commandoutput: Handle v3.2Copyright (C) 1997-2006 Mark RussinovichSysinternals - www.sysinternals.com
    No matching handles found.
    no other processes accesses file!
    Greift irgendein Prozess auf die Datei zu sieht die Ausgabe so aus:

    Code:
    pathToFileHandleTool:C:\tmp\Handle\handle.exe
    pathToFile: C:\tmp\openSUSE-10.2-GM-i386-CD3.iso
    expectedFileHandleSuccessOutput: (.*)No matching handles found(.*)
    we are on windows..
    bufferedReader not ready!
    bin vor readline!
    reading in line....
    reading in line....
    reading in line....
    reading in line....
    reading in line....
    reading in line....
    bin nach readline!
    commandoutput: Handle v3.2Copyright (C) 1997-2006 Mark RussinovichSysinternals - www.sysinternals.com
    WinSCP3.exe        pid: 1108    1AC: C:\tmp\openSUSE-10.2-GM-i386-CD3.iso.filepart
    one or more other processes access file!
    Also alles ok soweit, das Programm tut was es soll....

    Verwende ich aber nun __exakt__ denselben Code in meiner (Servlet-) Applikation funktioniert er nicht mehr:

    Code:
    	private boolean isWritten(File file) {	
    		
    		String pathToFileHandleTool = "C:\\tmp\\Handle\\handle.exe";
    		String pathToFile = "C:\\tmp\\openSUSE-10.2-GM-i386-CD3.iso";
    		String expectedFileHandleSuccessOutput = "(.*)No matching handles found(.*)";
    		logger.debug("pathToFileHandleTool: " + pathToFileHandleTool);
    		logger.debug("pathToFile: " + pathToFile);
    		logger.debug("expectedFileHandleSuccessOutput: " + expectedFileHandleSuccessOutput);
    				
    		ProcessBuilder builder = null;
    		// check for os
    		if(System.getProperty("os.name").matches("(.*)Windows(.*)")) {
    			logger.debug("we are on windows..");
    		} else {
    			logger.debug("we are on linux..");
    		}  
    		builder = new ProcessBuilder( pathToFileHandleTool, pathToFile);
    		Process process = null;
    		String commandOutput = "";
    		String line = null;
    		BufferedReader bufferedReader = null;
    		try {
    			process = builder.start();
    			// read command output
    			bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
    			if(!bufferedReader.ready()) {
    				logger.debug("bufferedReader not ready!");
    			}
    			logger.debug("bin vor readline!");
    	    		while((line = bufferedReader.readLine()) != null) {
    				commandOutput += line;
    				logger.debug("reading in line....");
    	    		}
    			logger.debug("bin nach readline!");
    			logger.debug("commandoutput: " + commandOutput);
    			// wait till process has finished
    			process.waitFor();
    		} catch (IOException e) {
    			logger.debug(e.getMessage());
    			logger.debug(e);
    		}  catch (InterruptedException e) {
    			logger.debug(e.getMessage());
    			logger.debug(e);
    		}
    		// check output to assure that no process uses file
    		if(commandOutput.matches(expectedFileHandleSuccessOutput)) {
    			logger.debug("no other processes accesses file!");
    			return true;
    		}
    		else {
    			logger.debug("one or more other processes access file!");
    			return false;
    		}	
    	}
    Nun sieht die Ausgabe so aus:

    Code:
     pathToFileHandleTool: C:\tmp\Handle\handle.exe
     pathToFile: C:\tmp\openSUSE-10.2-GM-i386-CD3.iso
     expectedFileHandleSuccessOutput: (.*)No matching handles found(.*)
     we are on windows..
     bufferedReader not ready
     bin vor readline!
    Sprich wie man sieht hängt es genau hier:

    Code:
    			logger.debug("bin vor readline!");
    	    	while((line = bufferedReader.readLine()) != null) {
    	    		commandOutput += line;
    	    		logger.debug("reading in line....");
    	    	}
    	    	logger.debug("bin nach readline!");
    Es passiert also einfach nichts mehr?!

    WTF ist hier los?

    Ich sehe keine relevanten Unterschiede zwischen dem Testprogramm und der Applikation, ich sehe nur
    3 Punkte die anders sind:

    1) Statt System.out.println wird logger.debug() verwendet -> unkritisch
    2) Die Methode in der Applikation enthält am Ende return-Statements -> unkritisch, bis dahin kommt es ja gar nicht
    3) Das Testprogramm starte ich direkt über "java TestIt" bzw. über Eclipse heraus, die Applikation
    ist eine Servlet-Applikation die über den Tomcat läuft. Aber alles was ich gestart habe, habe ich
    zu Testzwecken als Administrator gestartet, sprich sowohl Tomcat als auch das Programm in der
    Kommandozeile.

    Vielleicht sehe ich hier den Wald vor lauter Bäumen nicht mehr, aber es gibt IMHO keinen Unterschied...

    Anmerkung (1): pathToFileHandleTool, pathToFile usw. hab ich in der Applikation natürlich nicht fest verdrahtet,
    die Konfiguration läuft über spring. Sprich der ganze Kram ist hier nur zu debugging-Zwecken.Ebenso
    wie die ganzen Ausgaben.

    Anmerkung (2): Unter Linux mit "lsof" läuft sowohl die Applikation als auch das Testprogrammm

    Ich hoffe wirklich jemand hat eine Idee, weil ich hab jetzt keine Ahnung mehr woran das liegen könnte....
    Geändert von pr0nst1r (13-04-2007 um 21:53 Uhr)

  2. #2
    Registrierter Benutzer
    Registriert seit
    02.12.2002
    Ort
    Darmstadt
    Beiträge
    615
    Bin mir nicht ganz sicher, aber ich glaube du musst auch die Ausgabe von getOutputStream() und getErrorStream() holen, sprich die Streams leeren, sonst bleibt das Problem stehen.
    Seine Rätselhaftigkeit wird nur durch seine Macht übertroffen!

  3. #3
    Registrierter Benutzer
    Registriert seit
    14.03.2007
    Beiträge
    6
    Hi,

    Bin mir nicht ganz sicher, aber ich glaube du musst auch die Ausgabe von getOutputStream() und getErrorStream() holen, sprich die Streams leeren, sonst bleibt das Problem stehen.
    Hmmm,

    in der API-Doku steht aber:

    getInputStream

    public abstract InputStream getInputStream()

    Gets the input stream of the subprocess. The stream obtains data piped from the standard output stream of the process represented by this Process object.
    Den Output-Stream kriege ich damit ja schon mal.

    Ich hab jetzt noch folgende Sachen hinzugefügt, die ich neu probiert habe / vergessen zu erwähnen:

    -> error stream

    Code:
    builder.redirectErrorStream(true);
    hinzugefügt.

    Ergebis: Gar keines, sprich ich krieg immer noch keine Fehlerausgabe.

    -> Ich hatte vergessen zu erwähnen, bei dem relevanten Code-Ausschnitt:

    Code:
    			logger.debug("bin vor readline-Aufruf!");
    	    	while((line = bufferedReader.readLine()) != null) {
    	    		logger.debug("before reading in line....");
    	    		commandOutput += line;
    	    		logger.debug("after reading in line....");
    	    	}
    hängt die Applikation genau hier:

    Code:
    while((line = bufferedReader.readLine()) != null) {
    sprich zu

    Code:
    logger.debug("before reading in line....");
    kommt es nicht mehr.

    -> logs

    Auch die Tomcat-Logs bringen keine Error / Exception, die Ausgabe ist identisch zu dem was ich in meinen separaten logfiles mitlogge.

    -> die Rechte auf "handle.exe" sehen so aus, das "jeder" "Vollzugriff" hat.

    -> Um Betriebssystem-Fehler auszuschließen, hab ich es noch auf einer anderen Windows 2000 Maschine getestet. Ergebnis: Das Gleiche.

    -> Um zu testen, ob es daran liegt, das ich aus dem Tomcat heraus keine Applikationen aufrufen, hab ich mit dem identischen Code mal "nslookup www.google" aufgerufen, klappt aus der Applikation heraus einwandfrei.
    "Handle" greift aber auch nur lesend auf das System zu.

    Ich dachte mir, das evtl. der security manager des Tomcats da noch irgendwie rumpfuscht, das tomcat-manual sagt aber dazu:

    Once you have configured the catalina.policy file for use with a SecurityManager, Tomcat can be started with a SecurityManager in place by using the "-security" option
    Ich starte ihn ohne diese Option, daran sollte es nicht liegen.
    catalina.policy hab ich auch nicht angerührt.
    Und wie schon erwähnt: andere Programme kann ich ausführen..........

    Es muss doch irgendeinen Weg geben zumindest mal eine Fehlermeldung ausgeben zu lassen?

    Noch mal kurz zusammengefaßt:

    -> Handle in einer separaten Testklasse unter Windows -> funktioniert
    -> Handle in die Applikation eingebaut unter Windows -> funktioniert nicht
    -> identischer Code in die Applikation eingebaut unter linux ("handle" durch "lsof" ersetzt) funktioniert.

    Tja, nun hab ich keine Idee mehr.

    Bin für jeden noch so absurden Tipp zu haben.....
    Geändert von pr0nst1r (16-04-2007 um 13:43 Uhr)

  4. #4
    Administrator Avatar von anda_skoa
    Registriert seit
    17.11.2001
    Ort
    Graz, Österreich
    Beiträge
    5.477
    Probier mal ein read() statt einem readLine().
    Vielleicht gibt es aus irgendeinem Grund keine volle Zeile und steckt dann

    Ciao,
    _
    Qt/KDE Entwickler
    Debian Benutzer

  5. #5
    Registrierter Benutzer
    Registriert seit
    14.03.2007
    Beiträge
    6
    Hi,

    das hab ich gerade probiert:

    Code:
    			logger.debug("bin vor read()-Aufruf!");
    			int iChar = 0; 
    			
    	    	while((iChar = bufferedReader.read()) != -1) {
    	    		logger.debug("before reading in char....");
    	    		commandOutput += iChar;
    	    		logger.debug("after reading in char....");
    	    	}
    Das Resultat ist das gleiche:

    Code:
    bin vor read()-Aufruf!
    und dann hängt das Ganze wieder.......

    Was ich jetzt noch alles probiert (das nachstehende mag sinnlos erscheinen, aber wenn man so einen Hänger kriegt und keine Ausgabe probiert man halt jeden noch so bescheuerten Schritt durch):

    -> den BufferedReader durch einen InputStreamReader ersetzt:

    Code:
    InputStreamReader iStreamReader = new InputStreamReader(p.getInputStream());
    			int iChar = 0; 
    			//bufferedReader.f
    	    	while((iChar = iStreamReader.read()) != -1) {
    	    		logger.debug("before reading in char....");
    	    		commandOutput += iChar;
    	    		logger.debug("after reading in char....");
    	    	}
    Gleiches Ergebnis, sprich keines.

    -> statt dem ProcessBuilder Runtime.exec genommen:

    Code:
    	runtime = Runtime.getRuntime();
    			
    	Process p = runtime.exec("C:\\tmp\\Handle\\handle C:\\tmp\\openSUSE-10.2-GM-i386-CD3.iso");
    Gleiches Ergebnis, sprich keines.

    -> handle in den pfad aufgenommen

    Ergebnis:

    Code:
    IOException: CreateProcess:  error=2
    Das soll laut google heissen:

    Code:
    A value of 2 at that point means "file not found". One of the files in the process is missing.
    Tomcat scheint also Umgebungsvariablen zu ignorieren.

    Habs dann noch so probiert:

    Code:
    builder = new ProcessBuilder( "cmd", "/c", pathToFileHandleTool, pathToFile);
    und so:

    Code:
    Process process = runtime.exec( "cmd", "/c","C:\\tmp\\Handle\\handle.exe C:\\tmp\\openSUSE-10.2-GM-i386-CD3.iso");
    Also nochmal zusammengefasst:

    Rufe ich z.b. nslookup genau wie oben auf:

    Code:
    		ProcessBuilder builder = null;
    		builder = new ProcessBuilder( "cmd", "/c", "nslookup", "www.google.de");
    		builder.redirectErrorStream(true);
    		Process process = null;
    		String commandOutput = "";
    		BufferedReader bufferedReader = null;
    
    		try {
    			logger.debug("builder-call: new ProcessBuilder( cmd, /c, pathToFileHandleTool, pathToFile)");
    
    			process = builder.start();			
    			logger.debug("called builder.start()");
    			// read command output
    			bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
    			logger.debug("before read()-call...");
    			int iChar = 0; 
    	    	while((iChar = bufferedReader.read()) != -1) {
    	    		logger.debug("before reading in char....");
    	    		commandOutput += iChar;
    	    		logger.debug("after reading in char....");
    	    	}
    	    	logger.debug("after read() call....");
    	    	logger.debug("command-output: " + commandOutput);			
    			// wait till process has finished
    			process.waitFor();
    		} catch (IOException e) {
    			logger.debug(e.getMessage());
    			logger.debug(e);
    		}  catch (InterruptedException e) {
    			logger.debug(e.getMessage());
    			logger.debug(e);
    		}
    funktioniert!

    Rufe ich nun handle direkt auf:

    Code:
    		ProcessBuilder builder = null;
    		builder = new ProcessBuilder( "cmd", "/c", "C:\\tmp\\Handle\\handle.exe", "C:\\tmp\\foo");
    		
    		builder.redirectErrorStream(true);
    		Process process = null;
    		String commandOutput = "";
    		BufferedReader bufferedReader = null;
    
    		try {
    			logger.debug("builder-call: new ProcessBuilder( cmd, /c, pathToFileHandleTool, pathToFile)");
    			logger.debug("test mit handle!!!!!");
    			process = builder.start();			
    			logger.debug("called builder.start()");
    			// read command output
    			bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
    			logger.debug("before read()-call...");
    			int iChar = 0; 
    	    	while((iChar = bufferedReader.read()) != -1) {
    	    		logger.debug("before reading in char....");
    	    		commandOutput += iChar;
    	    		logger.debug("after reading in char....");
    	    	}
    	    	logger.debug("after read() call....");
    	    	logger.debug("command-output: " + commandOutput);			
    			// wait till process has finished
    			process.waitFor();
    		} catch (IOException e) {
    			logger.debug(e.getMessage());
    			logger.debug(e);
    		}  catch (InterruptedException e) {
    			logger.debug(e.getMessage());
    			logger.debug(e);
    		}
    hängt!

    Hab dann handle in das nslookup-Verzeichnis kopiert und probiert:

    Code:
    String pathToFileHandleTool = "C:\\WINNT\\system32\\handle.exe";
    hängt ebenso..........

    Eigentlich würde ich ja davon ausgehen, das es nur über Umwege möglich aus dem Tomcat heraus externe Programme zu starten, ABER:

    Mit nslookup klappt es ja auch, und das ist ja auch keine built-in feature sondern ein externes Programm....

    Sieht jemand wie das doch noch laufen könnte?
    Geändert von pr0nst1r (16-04-2007 um 20:40 Uhr)

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •