From 4dec40862e33d619d666c13c0d39070e51d7ee23 Mon Sep 17 00:00:00 2001 From: Alain Magloire Date: Tue, 16 Nov 2004 20:41:14 +0000 Subject: [PATCH] 2004-11-16 Alain Magloire FIX for 27663 * utils/org/eclipse/cdt/utils/pty/PTY.java * utils/org/eclipse/cdt/utils/spawner/ProcessFactory.java * utils/org/eclipse/cdt/utils/spawner/Spawner.java * utils/org/eclipse/cdt/utils/spawner/SpawnerInputStream.java --- core/org.eclipse.cdt.core/ChangeLog | 7 ++ .../utils/org/eclipse/cdt/utils/pty/PTY.java | 41 ++++--- .../cdt/utils/spawner/ProcessFactory.java | 14 ++- .../eclipse/cdt/utils/spawner/Spawner.java | 114 +++++++++++++++--- .../cdt/utils/spawner/SpawnerInputStream.java | 4 +- 5 files changed, 141 insertions(+), 39 deletions(-) diff --git a/core/org.eclipse.cdt.core/ChangeLog b/core/org.eclipse.cdt.core/ChangeLog index 484ffe708aa..8ba01304bcd 100644 --- a/core/org.eclipse.cdt.core/ChangeLog +++ b/core/org.eclipse.cdt.core/ChangeLog @@ -1,3 +1,10 @@ +2004-11-16 Alain Magloire + FIX for 27663 + * utils/org/eclipse/cdt/utils/pty/PTY.java + * utils/org/eclipse/cdt/utils/spawner/ProcessFactory.java + * utils/org/eclipse/cdt/utils/spawner/Spawner.java + * utils/org/eclipse/cdt/utils/spawner/SpawnerInputStream.java + 2004-11-14 Alain Magloire Fix for PR 77546. Make the error parser manager faster by diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/pty/PTY.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/pty/PTY.java index b8f5d1efddd..e001606d195 100644 --- a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/pty/PTY.java +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/pty/PTY.java @@ -11,24 +11,21 @@ package org.eclipse.cdt.utils.pty; import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; import org.eclipse.cdt.core.CCorePlugin; /** - * @author alain - * - * To change this generated comment edit the template variable "typecomment": - * Window>Preferences>Java>Templates. - * To enable and disable the creation of type comments go to - * Window>Preferences>Java>Code Generation. + * PTY + * pseudo terminal code. */ public class PTY { String slave; - InputStream in; - OutputStream out; + PTYInputStream in; + PTYOutputStream out; + /** + * NOTE: Field access by the native layer do not refactor. + */ int master; private static boolean hasPTY; @@ -43,14 +40,14 @@ public class PTY { return master; } - public void setFD(int fd) { + void setFD(int fd) { master = fd; } } public PTY() throws IOException { if (hasPTY) { - slave= forkpty(); + slave= openMaster(); } if (slave == null) { @@ -64,23 +61,33 @@ public class PTY { public String getSlaveName() { return slave; } - - public OutputStream getOutputStream() { + + public MasterFD getMasterFD() { + return new MasterFD(); + } + + public PTYOutputStream getOutputStream() { return out; } - public InputStream getInputStream() { + public PTYInputStream getInputStream() { return in; } - - native String forkpty(); + + public static boolean isSupported() { + return hasPTY; + } + + native String openMaster(); static { try { System.loadLibrary("pty"); //$NON-NLS-1$ hasPTY = true; } catch (SecurityException e) { + CCorePlugin.log(e); } catch (UnsatisfiedLinkError e) { + CCorePlugin.log(e); } } diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/spawner/ProcessFactory.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/spawner/ProcessFactory.java index ae4ffa313c4..ac285f6ce82 100644 --- a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/spawner/ProcessFactory.java +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/spawner/ProcessFactory.java @@ -14,6 +14,9 @@ package org.eclipse.cdt.utils.spawner; import java.io.File; import java.io.IOException; +import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.utils.pty.PTY; + public class ProcessFactory { static private ProcessFactory instance; @@ -33,9 +36,9 @@ public class ProcessFactory { hasSpawner = true; } } catch (SecurityException e) { - //e.printStackTrace(); + e.printStackTrace(); } catch (UnsatisfiedLinkError e) { - //e.printStackTrace(); + e.printStackTrace(); } } @@ -82,4 +85,11 @@ public class ProcessFactory { return new Spawner(cmdarray, envp, dir); return runtime.exec(cmdarray, envp, dir); } + + public Process exec(String cmdarray[], String[] envp, File dir, PTY pty) + throws IOException { + if (hasSpawner) + return new Spawner(cmdarray, envp, dir, pty); + throw new UnsupportedOperationException(CCorePlugin.getResourceString("Util.exception.cannotCreatePty")); //$NON-NLS-1$ + } } diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/spawner/Spawner.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/spawner/Spawner.java index 09c7c569d98..bb392e3681c 100644 --- a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/spawner/Spawner.java +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/spawner/Spawner.java @@ -18,6 +18,7 @@ import java.io.OutputStream; import java.util.StringTokenizer; import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.utils.pty.PTY; public class Spawner extends Process { @@ -29,7 +30,7 @@ public class Spawner extends Process { int pid = 0; int status; - int[] channels = new int[3]; + int[] fChannels = new int[3]; boolean isDone; OutputStream out; InputStream in; @@ -56,6 +57,12 @@ public class Spawner extends Process { exec(cmdarray, envp, dirpath); } + protected Spawner(String[] cmdarray, String[] envp, File dir, PTY pty) throws IOException { + String dirpath = "."; //$NON-NLS-1$ + if (dir != null) + dirpath = dir.getAbsolutePath(); + exec_pty(cmdarray, envp, dirpath, pty); + } /** * Executes the specified string command in a separate process. **/ @@ -222,9 +229,50 @@ public class Spawner extends Process { if (pid == -1) { throw new IOException("Exec error:" + reaper.getErrorMessage()); //$NON-NLS-1$ } - in = new SpawnerInputStream(channels[1]); - err = new SpawnerInputStream(channels[2]); - out = new SpawnerOutputStream(channels[0]); + in = new SpawnerInputStream(fChannels[1]); + err = new SpawnerInputStream(fChannels[2]); + out = new SpawnerOutputStream(fChannels[0]); + } + + private void exec_pty(String[] cmdarray, String[] envp, String dirpath, PTY pty) throws IOException { + String command = cmdarray[0]; + SecurityManager s = System.getSecurityManager(); + if (s != null) + s.checkExec(command); + if (envp == null) + envp = new String[0]; + + final String slaveName = pty.getSlaveName(); + final int masterFD = pty.getMasterFD().getFD(); + //int fdm = pty.get + Reaper reaper = new Reaper(cmdarray, envp, dirpath) { + /* (non-Javadoc) + * @see org.eclipse.cdt.utils.spawner.Spawner.Reaper#execute(java.lang.String[], java.lang.String[], java.lang.String, int[]) + */ + int execute(String[] cmd, String[] env, String dir, int[] channels) throws IOException { + return exec2(cmd, env, dir, channels, slaveName, masterFD); + } + }; + reaper.setDaemon(true); + reaper.start(); + + // Wait until the subprocess is started or error. + synchronized (this) { + while (pid == 0) { + try { + wait(); + } catch (InterruptedException e) { + } + } + } + + // Check for errors. + if (pid == -1) { + throw new IOException("Exec_tty error:" + reaper.getErrorMessage()); //$NON-NLS-1$ + } + in = new SpawnerInputStream(fChannels[1]); + err = new SpawnerInputStream(fChannels[2]); + out = new SpawnerOutputStream(fChannels[0]); } public void exec_detached(String[] cmdarray, String[] envp, String dirpath) throws IOException { @@ -241,13 +289,39 @@ public class Spawner extends Process { } } + /** + * Native method use in normal exec() calls. + */ native int exec0( String[] cmdarray, String[] envp, String dir, int[] chan) throws IOException; + + /** + * Native method use in no redirect meaning to streams will created. + */ native int exec1( String[] cmdarray, String[] envp, String dir) throws IOException; - public native int raise(int pid, int sig); - native int waitFor(int pid); + + /** + * Native method when executing with a terminal emulation. + */ + native int exec2( String[] cmdarray, String[] envp, String dir, int[] chan, String slaveName, int masterFD) throws IOException; + + /** + * Native method to drop a signal on the process with pid. + */ + public native int raise(int processID, int sig); + + /* + * Native method to wait(3) for process to terminate. + */ + native int waitFor(int processID); static { - System.loadLibrary("spawner"); //$NON-NLS-1$ + try { + System.loadLibrary("spawner"); //$NON-NLS-1$ + } catch (SecurityException e) { + CCorePlugin.log(e); + } catch (UnsatisfiedLinkError e) { + CCorePlugin.log(e); + } } // Spawn a thread to handle the forking and waiting @@ -255,25 +329,29 @@ public class Spawner extends Process { // send to the one thread. So do the forking and // the wait in the same thread. class Reaper extends Thread { - String[] cmdarray; - String[] envp; - String dirpath; - String errMesg; + String[] fCmdarray; + String[] fEnvp; + String fDirpath; + String fErrMesg; public Reaper(String[] array, String[] env, String dir) { super("Spawner Reaper"); //$NON-NLS-1$ - cmdarray = array; - envp = env; - dirpath = dir; - errMesg = new String(CCorePlugin.getResourceString("Util.error.cannotRun") + cmdarray[0]); //$NON-NLS-1$ + fCmdarray = array; + fEnvp = env; + fDirpath = dir; + fErrMesg = new String(CCorePlugin.getResourceString("Util.error.cannotRun") + fCmdarray[0]); //$NON-NLS-1$ + } + + int execute(String[] cmdarray, String[] envp, String dir, int[] channels) throws IOException { + return exec0(cmdarray, envp, dir, channels); } public void run() { try { - pid = exec0(cmdarray, envp, dirpath, channels); + pid = execute(fCmdarray, fEnvp, fDirpath, fChannels); } catch (Exception e) { pid = -1; - errMesg = e.getMessage(); + fErrMesg = e.getMessage(); } // Tell spawner that the process started. @@ -292,7 +370,7 @@ public class Spawner extends Process { } public String getErrorMessage() { - return errMesg; + return fErrMesg; } } } diff --git a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/spawner/SpawnerInputStream.java b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/spawner/SpawnerInputStream.java index dc1e8e3e21d..df58fbc474f 100644 --- a/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/spawner/SpawnerInputStream.java +++ b/core/org.eclipse.cdt.core/utils/org/eclipse/cdt/utils/spawner/SpawnerInputStream.java @@ -78,8 +78,8 @@ class SpawnerInputStream extends InputStream { fd = -1; } - private native int read0(int fd, byte[] buf, int len) throws IOException; - private native int close0(int fd) throws IOException; + private native int read0(int fileDesc, byte[] buf, int len) throws IOException; + private native int close0(int fileDesc) throws IOException; static { System.loadLibrary("spawner"); //$NON-NLS-1$