mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-24 01:15:29 +02:00
Update the starter/spawner to use named pipes.
Patch from alex.
This commit is contained in:
parent
385ac1b870
commit
c2ba759a8c
13 changed files with 482 additions and 203 deletions
|
@ -1,3 +1,8 @@
|
|||
2004-02-12 Alex Chapiro
|
||||
|
||||
Update starter and spawner to use named pipes.
|
||||
Update the binaries.
|
||||
|
||||
2003-08-29 Alex Chapiro
|
||||
|
||||
This patch just increase command line buffer up to OS limit (2K). It also
|
||||
|
|
|
@ -1,3 +1,17 @@
|
|||
/**********************************************************************
|
||||
* Copyright (c) 2002-2004 QNX Software Systems and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* QNX Software Systems - Initial API and implementation
|
||||
*
|
||||
* Spawner.h
|
||||
*
|
||||
* This is a part of JNI implementation of spawner
|
||||
***********************************************************************/
|
||||
/* DO NOT EDIT THIS FILE - it is machine generated */
|
||||
#include <jni.h>
|
||||
/* Header for class org_eclipse_cdt_utils_spawner_Spawner */
|
||||
|
@ -40,9 +54,15 @@ JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_raise
|
|||
JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_waitFor
|
||||
(JNIEnv *, jobject, jint);
|
||||
|
||||
// #define DEBUG_MONITOR
|
||||
|
||||
int interruptProcess(int pid);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
// #define DEBUG_MONITOR
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,3 +1,18 @@
|
|||
/**********************************************************************
|
||||
* Copyright (c) 2002-2004 QNX Software Systems and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* QNX Software Systems - Initial API and implementation
|
||||
*
|
||||
* SpawnerInputStream.h
|
||||
*
|
||||
* This is a part of JNI implementation of spawner
|
||||
***********************************************************************/
|
||||
|
||||
/* DO NOT EDIT THIS FILE - it is machine generated */
|
||||
#include <jni.h>
|
||||
/* Header for class com_qnx_tools_utils_spawner_SpawnerInputStream */
|
||||
|
|
|
@ -1,3 +1,17 @@
|
|||
/**********************************************************************
|
||||
* Copyright (c) 2002-2004 QNX Software Systems and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* QNX Software Systems - Initial API and implementation
|
||||
*
|
||||
* SpawnerOutputStream.h
|
||||
*
|
||||
* This is a part of JNI implementation of spawner
|
||||
***********************************************************************/
|
||||
/* DO NOT EDIT THIS FILE - it is machine generated */
|
||||
#include <jni.h>
|
||||
/* Header for class com_qnx_tools_utils_spawner_SpawnerOutputStream */
|
||||
|
|
|
@ -1,12 +1,16 @@
|
|||
/**********************************************************************
|
||||
* Copyright (c) 2002,2003 QNX Software Systems and others.
|
||||
* Copyright (c) 2002-2004 QNX Software Systems and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v0.5
|
||||
* are made available under the terms of the Common Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v05.html
|
||||
* http://www.eclipse.org/legal/cpl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* QNX Software Systems - Initial API and implementation
|
||||
*
|
||||
* StdAfx.c
|
||||
*
|
||||
* This is a part of JNI implementation of spawner
|
||||
***********************************************************************/
|
||||
// stdafx.cpp : source file that includes just the standard includes
|
||||
// spawner.pch will be the pre-compiled header
|
||||
|
|
|
@ -1,13 +1,18 @@
|
|||
/**********************************************************************
|
||||
* Copyright (c) 2002,2003 QNX Software Systems and others.
|
||||
* Copyright (c) 2002-2004 QNX Software Systems and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v0.5
|
||||
* are made available under the terms of the Common Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v05.html
|
||||
* http://www.eclipse.org/legal/cpl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* QNX Software Systems - Initial API and implementation
|
||||
*
|
||||
* StdAfx.h
|
||||
*
|
||||
* This is a part of JNI implementation of spawner
|
||||
***********************************************************************/
|
||||
|
||||
// stdafx.h : include file for standard system include files,
|
||||
// or project specific include files that are used frequently, but
|
||||
// are changed infrequently
|
||||
|
|
|
@ -1,59 +1,76 @@
|
|||
/**********************************************************************
|
||||
* Copyright (c) 2002,2003 QNX Software Systems and others.
|
||||
* Copyright (c) 2002-2004 QNX Software Systems and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v0.5
|
||||
* are made available under the terms of the Common Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v05.html
|
||||
* http://www.eclipse.org/legal/cpl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* QNX Software Systems - Initial API and implementation
|
||||
***********************************************************************/
|
||||
/*
|
||||
*
|
||||
* Win32ProcessEx.c
|
||||
*
|
||||
* This is a JNI implementation of spawner
|
||||
*/
|
||||
***********************************************************************/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <process.h>
|
||||
#include "Spawner.h"
|
||||
|
||||
|
||||
#include "jni.h"
|
||||
#include "io.h"
|
||||
|
||||
|
||||
#define PIPE_SIZE 512 // Size of pipe buffer
|
||||
#define MAX_CMD_SIZE 2049 // Maximum size of command line
|
||||
#define MAX_ENV_SIZE 4096 // Initial size of environment block
|
||||
#define PIPE_NAME_LENGTH 100 // Size of pipe name buffer
|
||||
#define PIPE_TIMEOUT 10000 // Default time-out value, in milliseconds.
|
||||
|
||||
#include "jni.h"
|
||||
#include "io.h"
|
||||
|
||||
// #define DEBUG_MONITOR
|
||||
|
||||
#define PIPE_SIZE 512
|
||||
#define MAX_CMD_SIZE 2049
|
||||
#define MAX_ENV_SIZE 4096
|
||||
|
||||
#define MAX_PROCS (100)
|
||||
#define MAX_PROCS (100) // Maximum number of simultaneiously runnig processes
|
||||
|
||||
// Theses are VM helpers
|
||||
typedef JNIEXPORT void * (JNICALL * JVM_GetThreadInterruptEvent)();
|
||||
typedef JNIEXPORT char * (JNICALL * JVM_NativePath)(const char *);
|
||||
|
||||
// Process description block. Should be created for each launched process
|
||||
typedef struct _procInfo {
|
||||
int pid; // Process ID
|
||||
int uid; // quasi-unique process ID
|
||||
int uid; // quasi-unique process ID; we have to create it to avoid duplicated pid
|
||||
// (actually this impossible from OS point of view but it is still possible
|
||||
// a clash of new created and already finished process with one and the same PID.
|
||||
// 3 events connected to this process (see starter)
|
||||
HANDLE eventBreak;
|
||||
HANDLE eventWait;
|
||||
HANDLE eventTerminate;
|
||||
} procInfo_t, * pProcInfo_t;
|
||||
|
||||
static int procCounter = 0;
|
||||
static int procCounter = 0; // Number of running processes
|
||||
|
||||
|
||||
// This is a VM helper
|
||||
JNIEXPORT void JNICALL ThrowByName(JNIEnv *env, const char *name, const char *msg);
|
||||
pProcInfo_t createProcInfo();
|
||||
pProcInfo_t findProcInfo(int pid);
|
||||
|
||||
// Creates _procInfo block for every launched procss
|
||||
pProcInfo_t createProcInfo();
|
||||
|
||||
// Find process description for this pid
|
||||
pProcInfo_t findProcInfo(int pid);
|
||||
|
||||
// We launch separate thread for each project to trap it termination
|
||||
unsigned int _stdcall waitProcTermination(void* pv) ;
|
||||
|
||||
// This is a helper function to prevent losing of quotatin marks
|
||||
static int copyTo(char * target, const char * source, int cpyLenght, int availSpace);
|
||||
|
||||
// Use this function to clean project descriptor and return it to the pool of available blocks.
|
||||
static void cleanUpProcBlock(pProcInfo_t pCurProcInfo);
|
||||
|
||||
|
||||
|
||||
// Signal codes
|
||||
typedef enum {
|
||||
SIG_NOOP,
|
||||
SIG_HUP,
|
||||
|
@ -65,20 +82,27 @@ typedef enum {
|
|||
extern CRITICAL_SECTION cs;
|
||||
|
||||
|
||||
extern TCHAR path[MAX_PATH];
|
||||
extern TCHAR path[MAX_PATH]; // Directory where spawner.dll is located
|
||||
|
||||
static HMODULE hVM = NULL;
|
||||
static HMODULE hVM = NULL; // VM handler
|
||||
|
||||
|
||||
static pProcInfo_t pInfo = NULL;
|
||||
|
||||
static int nCounter = 0; // We use it to build unique synchronisation object names
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
// Launcher; launchess process and traps its termination
|
||||
// Arguments: (see Spawner.java)
|
||||
// [in] cmdarray - array of command line elements
|
||||
// [in] envp - array of environment variables
|
||||
// [in] dir - working directory
|
||||
// [out] channels - streams handlers
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_exec0
|
||||
(JNIEnv * env, jobject process, jobjectArray cmdarray, jobjectArray envp, jstring dir, jintArray channels)
|
||||
{
|
||||
|
||||
HANDLE hread[3], hwrite[3];
|
||||
SECURITY_ATTRIBUTES sa;
|
||||
HANDLE stdHandles[3];
|
||||
PROCESS_INFORMATION pi = {0};
|
||||
STARTUPINFO si;
|
||||
DWORD flags = 0;
|
||||
|
@ -91,6 +115,7 @@ JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_exec0
|
|||
jsize nCmdTokens = 0;
|
||||
jsize nEnvVars = 0;
|
||||
int i;
|
||||
DWORD pid = GetCurrentProcessId();
|
||||
int nPos;
|
||||
pProcInfo_t pCurProcInfo;
|
||||
DWORD dwThreadId;
|
||||
|
@ -100,6 +125,10 @@ JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_exec0
|
|||
#ifdef DEBUG_MONITOR
|
||||
char buffer[1000];
|
||||
#endif
|
||||
int nLocalCounter;
|
||||
char inPipeName[PIPE_NAME_LENGTH];
|
||||
char outPipeName[PIPE_NAME_LENGTH];
|
||||
char errPipeName[PIPE_NAME_LENGTH];
|
||||
|
||||
if((HIBYTE(LOWORD(GetVersion()))) & 0x80)
|
||||
{
|
||||
|
@ -113,25 +142,39 @@ JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_exec0
|
|||
return 0;
|
||||
}
|
||||
|
||||
sa.nLength = sizeof(sa);
|
||||
sa.lpSecurityDescriptor = 0;
|
||||
sa.bInheritHandle = TRUE;
|
||||
ZeroMemory(stdHandles, sizeof(stdHandles));
|
||||
|
||||
memset(hread, 0, sizeof(hread));
|
||||
memset(hwrite, 0, sizeof(hwrite));
|
||||
if (!(CreatePipe(&hread[0], &hwrite[0], &sa, PIPE_SIZE) &&
|
||||
CreatePipe(&hread[1], &hwrite[1], &sa, PIPE_SIZE) &&
|
||||
CreatePipe(&hread[2], &hwrite[2], &sa, PIPE_SIZE)))
|
||||
{
|
||||
CloseHandle(hread[0]);
|
||||
CloseHandle(hread[1]);
|
||||
CloseHandle(hread[2]);
|
||||
CloseHandle(hwrite[0]);
|
||||
CloseHandle(hwrite[1]);
|
||||
CloseHandle(hwrite[2]);
|
||||
// Create pipe names
|
||||
EnterCriticalSection(&cs);
|
||||
sprintf(inPipeName, "\\\\.\\pipe\\stdin%08i%010i", pid, nCounter);
|
||||
sprintf(outPipeName, "\\\\.\\pipe\\stdout%08i%010i", pid, nCounter);
|
||||
sprintf(errPipeName, "\\\\.\\pipe\\stderr%08i%010i", pid, nCounter);
|
||||
nLocalCounter = nCounter;
|
||||
++nCounter;
|
||||
LeaveCriticalSection(&cs);
|
||||
|
||||
|
||||
if ((INVALID_HANDLE_VALUE == (stdHandles[0] = CreateNamedPipe(inPipeName, PIPE_ACCESS_OUTBOUND,
|
||||
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
|
||||
PIPE_UNLIMITED_INSTANCES, PIPE_SIZE, PIPE_SIZE, PIPE_TIMEOUT, NULL))) ||
|
||||
(INVALID_HANDLE_VALUE == (stdHandles[1] = CreateNamedPipe(outPipeName, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED,
|
||||
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
|
||||
PIPE_UNLIMITED_INSTANCES, PIPE_SIZE, PIPE_SIZE, PIPE_TIMEOUT, NULL))) ||
|
||||
(INVALID_HANDLE_VALUE == (stdHandles[2] = CreateNamedPipe(errPipeName, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED,
|
||||
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
|
||||
PIPE_UNLIMITED_INSTANCES, PIPE_SIZE, PIPE_SIZE, PIPE_TIMEOUT, NULL)))) {
|
||||
CloseHandle(stdHandles[0]);
|
||||
CloseHandle(stdHandles[1]);
|
||||
CloseHandle(stdHandles[2]);
|
||||
ThrowByName(env, "java/io/IOException", "CreatePipe");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_MONITOR
|
||||
sprintf(buffer, "Opened pipes: %s, %s, %s\n", inPipeName, outPipeName, errPipeName);
|
||||
OutputDebugString(buffer);
|
||||
#endif
|
||||
|
||||
|
||||
nCmdTokens = (*env) -> GetArrayLength(env, cmdarray);
|
||||
nEnvVars = (*env) -> GetArrayLength(env, envp);
|
||||
|
@ -144,17 +187,18 @@ JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_exec0
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// Construct starter's command line
|
||||
sprintf(eventBreakName, "SABreak%p", pCurProcInfo);
|
||||
sprintf(eventWaitName, "SAWait%p", pCurProcInfo);
|
||||
sprintf(eventTerminateName, "SATerm%p", pCurProcInfo);
|
||||
pCurProcInfo -> eventBreak = CreateEvent(NULL, TRUE, FALSE, eventBreakName);
|
||||
ResetEvent(pCurProcInfo -> eventBreak);
|
||||
pCurProcInfo -> eventWait = CreateEvent(NULL, TRUE, FALSE, eventWaitName);
|
||||
ResetEvent(pCurProcInfo -> eventWait);
|
||||
pCurProcInfo -> eventTerminate = CreateEvent(NULL, TRUE, FALSE, eventTerminateName);
|
||||
ResetEvent(pCurProcInfo -> eventTerminate);
|
||||
|
||||
nPos = sprintf(szCmdLine, "%sstarter.exe %s %s %s ", path, eventBreakName, eventWaitName, eventTerminateName);
|
||||
nPos = sprintf(szCmdLine, "%sstarter.exe %i %i %s %s %s ", path, pid, nLocalCounter, eventBreakName, eventWaitName, eventTerminateName);
|
||||
|
||||
// Prepare command line
|
||||
for(i = 0; i < nCmdTokens; ++i)
|
||||
|
@ -229,21 +273,16 @@ JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_exec0
|
|||
}
|
||||
|
||||
|
||||
memset(&si, 0, sizeof(si));
|
||||
ZeroMemory(&si, sizeof(si));
|
||||
si.cb = sizeof(si);
|
||||
si.dwFlags |= STARTF_USESTDHANDLES;
|
||||
si.dwFlags |= STARTF_USESHOWWINDOW;
|
||||
si.wShowWindow = SW_HIDE; // Processes in the Process Group are hidden
|
||||
si.hStdInput = hread[0];
|
||||
si.hStdOutput = hwrite[1];
|
||||
si.hStdError = hwrite[2];
|
||||
|
||||
|
||||
|
||||
|
||||
SetHandleInformation(hwrite[0], HANDLE_FLAG_INHERIT, FALSE);
|
||||
SetHandleInformation(hread[1], HANDLE_FLAG_INHERIT, FALSE);
|
||||
SetHandleInformation(hread[2], HANDLE_FLAG_INHERIT, FALSE);
|
||||
SetHandleInformation(stdHandles[0], HANDLE_FLAG_INHERIT, FALSE);
|
||||
SetHandleInformation(stdHandles[1], HANDLE_FLAG_INHERIT, FALSE);
|
||||
SetHandleInformation(stdHandles[2], HANDLE_FLAG_INHERIT, FALSE);
|
||||
|
||||
flags = CREATE_NEW_CONSOLE;
|
||||
flags |= CREATE_NO_WINDOW;
|
||||
|
@ -251,14 +290,15 @@ JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_exec0
|
|||
#ifdef DEBUG_MONITOR
|
||||
OutputDebugString(szCmdLine);
|
||||
#endif
|
||||
|
||||
// launches starter; we need it to create another console group to correctly process
|
||||
// emulation of SYSint signal (Ctrl-C)
|
||||
ret = CreateProcess(0, /* executable name */
|
||||
szCmdLine, /* command line */
|
||||
szCmdLine, /* command line */
|
||||
0, /* process security attribute */
|
||||
0, /* thread security attribute */
|
||||
TRUE, /* inherits system handles */
|
||||
FALSE, /* inherits system handles */
|
||||
flags, /* normal attached process */
|
||||
envBlk, /* environment block */
|
||||
envBlk, /* environment block */
|
||||
cwd, /* change to the new current directory */
|
||||
&si, /* (in) startup information */
|
||||
&pi); /* (out) process information */
|
||||
|
@ -270,18 +310,13 @@ JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_exec0
|
|||
|
||||
free(szEnvBlock);
|
||||
|
||||
CloseHandle(hread[0]);
|
||||
CloseHandle(hwrite[1]);
|
||||
CloseHandle(hwrite[2]);
|
||||
|
||||
|
||||
if (!ret)
|
||||
if (!ret) // Launching error
|
||||
{
|
||||
LPTSTR lpMsgBuf;
|
||||
|
||||
CloseHandle(hwrite[0]);
|
||||
CloseHandle(hread[1]);
|
||||
CloseHandle(hread[2]);
|
||||
CloseHandle(stdHandles[0]);
|
||||
CloseHandle(stdHandles[1]);
|
||||
CloseHandle(stdHandles[2]);
|
||||
FormatMessage(
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
|
@ -327,18 +362,19 @@ JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_exec0
|
|||
}
|
||||
else
|
||||
{
|
||||
#ifdef DEBUG_MONITOR
|
||||
sprintf(buffer, "Process %i created\n", pi.dwProcessId);
|
||||
OutputDebugString(buffer);
|
||||
#endif
|
||||
ret = (long)(pCurProcInfo -> uid);
|
||||
file_handles[0] = (int)hwrite[0];
|
||||
file_handles[1] = (int)hread[1];
|
||||
file_handles[2] = (int)hread[2];
|
||||
|
||||
// Prepare stream handlers to return to java program
|
||||
file_handles[0] = (int)stdHandles[0];
|
||||
file_handles[1] = (int)stdHandles[1];
|
||||
file_handles[2] = (int)stdHandles[2];
|
||||
(*env) -> SetIntArrayRegion(env, channels, 0, 3, file_handles);
|
||||
}
|
||||
CloseHandle(h[1]);
|
||||
LeaveCriticalSection(&cs);
|
||||
#ifdef DEBUG_MONITOR
|
||||
OutputDebugString("Process started\n");
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
@ -348,6 +384,13 @@ JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_exec0
|
|||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
// Launcher; just launches process and don't care about it any more
|
||||
// Arguments: (see Spawner.java)
|
||||
// [in] cmdarray - array of command line elements
|
||||
// [in] envp - array of environment variables
|
||||
// [in] dir - working directory
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_exec1
|
||||
(JNIEnv * env, jobject process, jobjectArray cmdarray, jobjectArray envp, jstring dir)
|
||||
{
|
||||
|
@ -389,7 +432,7 @@ JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_exec1
|
|||
{
|
||||
if(0 > (nCpyLen = copyTo(szCmdLine + nPos, str, len, MAX_CMD_SIZE - nPos)))
|
||||
{
|
||||
ThrowByName(env, "java/io/IOException", "Too long command line");
|
||||
ThrowByName(env, "java/io/Exception", "Too long command line");
|
||||
return 0;
|
||||
}
|
||||
nPos += nCpyLen;
|
||||
|
@ -418,7 +461,7 @@ JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_exec1
|
|||
szEnvBlock = (char *)realloc(szEnvBlock, nBlkSize);
|
||||
if(NULL == szEnvBlock)
|
||||
{
|
||||
ThrowByName(env, "java/io/IOException", "Not enough memory");
|
||||
ThrowByName(env, "java/io/Exception", "Not enough memory");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -446,7 +489,7 @@ JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_exec1
|
|||
}
|
||||
|
||||
|
||||
memset(&si, 0, sizeof(si));
|
||||
ZeroMemory(&si, sizeof(si));
|
||||
si.cb = sizeof(si);
|
||||
|
||||
|
||||
|
@ -472,7 +515,7 @@ JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_exec1
|
|||
free(cwd);
|
||||
free(szEnvBlock);
|
||||
|
||||
if (!ret)
|
||||
if (!ret) // error
|
||||
{
|
||||
LPTSTR lpMsgBuf;
|
||||
|
||||
|
@ -494,6 +537,7 @@ JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_exec1
|
|||
}
|
||||
else
|
||||
{
|
||||
// Clean-up
|
||||
CloseHandle(pi.hThread);
|
||||
CloseHandle(pi.hProcess);
|
||||
ret = (long)pi.dwProcessId; //hProcess;
|
||||
|
@ -505,6 +549,12 @@ JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_exec1
|
|||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
// Emulation of the signal raising
|
||||
// Arguments: (see Spawner.java)
|
||||
// [in] uid - unique process ID
|
||||
// [in] signal - signal to raise
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_raise
|
||||
(JNIEnv * env, jobject process, jint uid, jint signal)
|
||||
{
|
||||
|
@ -570,13 +620,18 @@ JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_raise
|
|||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
// Wait for process termination
|
||||
// Arguments: (see Spawner.java)
|
||||
// [in] uid - unique process ID
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_waitFor
|
||||
(JNIEnv * env, jobject process, jint uid)
|
||||
{
|
||||
long exit_code;
|
||||
int what=0;
|
||||
{
|
||||
long exit_code;
|
||||
int what=0;
|
||||
HANDLE hProc;
|
||||
pProcInfo_t pCurProcInfo = findProcInfo(uid);
|
||||
|
||||
|
@ -590,25 +645,31 @@ JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_waitFor
|
|||
|
||||
what = WaitForSingleObject(hProc, INFINITE);
|
||||
|
||||
|
||||
|
||||
if (what == WAIT_OBJECT_0)
|
||||
{
|
||||
GetExitCodeProcess(hProc, &exit_code);
|
||||
{
|
||||
GetExitCodeProcess(hProc, &exit_code);
|
||||
}
|
||||
|
||||
|
||||
if(hProc)
|
||||
CloseHandle(hProc);
|
||||
|
||||
return exit_code;
|
||||
}
|
||||
|
||||
|
||||
|
||||
return exit_code;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Utilities
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
// Throws Java exception (will be trapped by VM).
|
||||
// Arguments:
|
||||
// [in] name - name of exception class
|
||||
// [in] message to assign thi event
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
JNIEXPORT void JNICALL
|
||||
ThrowByName(JNIEnv *env, const char *name, const char *msg)
|
||||
{
|
||||
|
@ -624,6 +685,11 @@ ThrowByName(JNIEnv *env, const char *name, const char *msg)
|
|||
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
// Create process description block.
|
||||
// Arguments: no
|
||||
// Return : pointer to the process descriptor
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
pProcInfo_t createProcInfo()
|
||||
{
|
||||
int i;
|
||||
|
@ -634,7 +700,7 @@ pProcInfo_t createProcInfo()
|
|||
if(NULL == pInfo)
|
||||
{
|
||||
pInfo = malloc(sizeof(procInfo_t) * MAX_PROCS);
|
||||
memset(pInfo, 0, sizeof(procInfo_t) * MAX_PROCS);
|
||||
ZeroMemory(pInfo, sizeof(procInfo_t) * MAX_PROCS);
|
||||
}
|
||||
|
||||
for(i = 0; i < MAX_PROCS; ++i)
|
||||
|
@ -653,6 +719,11 @@ pProcInfo_t createProcInfo()
|
|||
return p;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
// Using unique process ID finds process descriptor
|
||||
// Arguments: no
|
||||
// Return : pointer to the process descriptor
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
pProcInfo_t findProcInfo(int uid)
|
||||
{
|
||||
int i;
|
||||
|
@ -672,6 +743,11 @@ pProcInfo_t findProcInfo(int uid)
|
|||
return p;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
// Cleans up vacant process descriptor
|
||||
// Arguments:
|
||||
// pCurProcInfo - pointer to descriptor to clean up
|
||||
// Return : no
|
||||
void cleanUpProcBlock(pProcInfo_t pCurProcInfo)
|
||||
{
|
||||
if(0 != pCurProcInfo -> eventBreak)
|
||||
|
@ -693,11 +769,16 @@ void cleanUpProcBlock(pProcInfo_t pCurProcInfo)
|
|||
pCurProcInfo -> pid = 0;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
// Running in separae thread and waiting for the process termination
|
||||
// Arguments:
|
||||
// pv - (int)pv is a pid
|
||||
// Return : always 0
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
unsigned int _stdcall waitProcTermination(void* pv)
|
||||
{
|
||||
int i;
|
||||
int pid = (int)pv;
|
||||
DWORD rc = 0;
|
||||
#ifdef DEBUG_MONITOR
|
||||
char buffer[1000];
|
||||
#endif
|
||||
|
@ -742,7 +823,15 @@ unsigned int _stdcall waitProcTermination(void* pv)
|
|||
return 0;
|
||||
}
|
||||
|
||||
// Return number of bytes in target or -1 in case of error
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
// Use this utility program to process correctly quotation marks in the command line
|
||||
// Arguments:
|
||||
// target - string to copy to
|
||||
// source - string to copy from
|
||||
// cpyLength - copy length
|
||||
// availSpace - size of the target buffer
|
||||
// Return :number of bytes used in target, or -1 in case of error
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
int copyTo(char * target, const char * source, int cpyLength, int availSpace)
|
||||
{
|
||||
BOOL bSlash = FALSE;
|
||||
|
|
|
@ -1,23 +1,25 @@
|
|||
/**********************************************************************
|
||||
* Copyright (c) 2002,2003 QNX Software Systems and others.
|
||||
* Copyright (c) 2002-2004 QNX Software Systems and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v0.5
|
||||
* are made available under the terms of the Common Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v05.html
|
||||
* http://www.eclipse.org/legal/cpl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* QNX Software Systems - Initial API and implementation
|
||||
*
|
||||
* raise.c
|
||||
*
|
||||
* This is a part of JNI implementation of spawner
|
||||
* Includes implementation of JNI methods (see Spawner.java)
|
||||
***********************************************************************/
|
||||
/*
|
||||
* This is a JNI implementation of access to standard i/o streams
|
||||
*/
|
||||
#include "stdafx.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "spawner.h"
|
||||
#include "SpawnerInputStream.h"
|
||||
#include "SpawnerOutputStream.h"
|
||||
|
||||
|
||||
#include "jni.h"
|
||||
#include "io.h"
|
||||
|
||||
|
@ -37,35 +39,87 @@ JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_SpawnerInputStream_rea
|
|||
{
|
||||
BYTE tmpBuf[BUFF_SIZE];
|
||||
int nBuffOffset = 0;
|
||||
#ifdef DEBUG_MONITOR
|
||||
char buffer[1000];
|
||||
#endif
|
||||
OVERLAPPED overlapped;
|
||||
overlapped.Offset = 0;
|
||||
overlapped.OffsetHigh = 0;
|
||||
overlapped.hEvent = CreateEvent(NULL, // no security attribute
|
||||
TRUE, // manual-reset event
|
||||
TRUE, // initial state = signaled
|
||||
NULL); // unnamed event object
|
||||
|
||||
if(NULL == overlapped.hEvent) {
|
||||
LPTSTR lpMsgBuf;
|
||||
FormatMessage(
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL,
|
||||
GetLastError(),
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
|
||||
(LPTSTR) &lpMsgBuf,
|
||||
0,
|
||||
NULL
|
||||
);
|
||||
|
||||
ThrowByName(env, "java/io/IOException", lpMsgBuf);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_MONITOR
|
||||
sprintf(buffer, "Start read %i\n", fd);
|
||||
OutputDebugString(buffer);
|
||||
#endif
|
||||
|
||||
while(len > nBuffOffset)
|
||||
{
|
||||
int nNumberOfBytesToRead = min(len - nBuffOffset, BUFF_SIZE);
|
||||
int nNumberOfBytesRead;
|
||||
if(0 == ReadFile((HANDLE)fd, tmpBuf, nNumberOfBytesToRead, &nNumberOfBytesRead, NULL ))
|
||||
if(0 == ReadFile((HANDLE)fd, tmpBuf, nNumberOfBytesToRead, &nNumberOfBytesRead, &overlapped ))
|
||||
{
|
||||
LPTSTR lpMsgBuf;
|
||||
int err = GetLastError();
|
||||
|
||||
if(err == ERROR_IO_PENDING)
|
||||
{
|
||||
// asynchronous i/o is still in progress
|
||||
// check on the results of the asynchronous read
|
||||
if(GetOverlappedResult((HANDLE)fd, &overlapped,
|
||||
&nNumberOfBytesRead, TRUE))
|
||||
err = 0;
|
||||
// if there was a problem ...
|
||||
else
|
||||
err = GetLastError();
|
||||
}
|
||||
if(err == ERROR_BROKEN_PIPE) // Pipe was closed
|
||||
return 0;
|
||||
if(err != ERROR_MORE_DATA) // Otherwise error means just that there are more data
|
||||
{ // than buffer can accept
|
||||
FormatMessage(
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL,
|
||||
err,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
|
||||
(LPTSTR) &lpMsgBuf,
|
||||
0,
|
||||
NULL
|
||||
);
|
||||
break;
|
||||
if(err != 0)
|
||||
{
|
||||
LPTSTR lpMsgBuf;
|
||||
#ifdef DEBUG_MONITOR
|
||||
char buffer[200];
|
||||
sprintf(buffer, "Read failed - %i, error %i\n", fd, err);
|
||||
OutputDebugString(buffer);
|
||||
#endif
|
||||
if(err != ERROR_MORE_DATA) // Otherwise error means just that there are more data
|
||||
{ // than buffer can accept
|
||||
FormatMessage(
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL,
|
||||
err,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
|
||||
(LPTSTR) &lpMsgBuf,
|
||||
0,
|
||||
NULL
|
||||
);
|
||||
|
||||
ThrowByName(env, "java/io/IOException", lpMsgBuf);
|
||||
LocalFree( lpMsgBuf );
|
||||
return 0;
|
||||
ThrowByName(env, "java/io/IOException", lpMsgBuf);
|
||||
LocalFree( lpMsgBuf );
|
||||
nBuffOffset = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(nNumberOfBytesRead > 0)
|
||||
|
@ -76,6 +130,11 @@ JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_SpawnerInputStream_rea
|
|||
if(nNumberOfBytesRead != nNumberOfBytesToRead)
|
||||
break;
|
||||
}
|
||||
CloseHandle(overlapped.hEvent);
|
||||
#ifdef DEBUG_MONITOR
|
||||
sprintf(buffer, "End read %i\n", fd);
|
||||
OutputDebugString(buffer);
|
||||
#endif
|
||||
return nBuffOffset; // This is a real full readed length
|
||||
|
||||
}
|
||||
|
@ -88,7 +147,19 @@ JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_SpawnerInputStream_rea
|
|||
JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_SpawnerInputStream_close0
|
||||
(JNIEnv * env, jobject proc, jint fd)
|
||||
{
|
||||
return (CloseHandle((HANDLE)fd) ? 0 : -1);
|
||||
int rc;
|
||||
#ifdef DEBUG_MONITOR
|
||||
char buffer[1000];
|
||||
sprintf(buffer, "Close %i\n", fd);
|
||||
OutputDebugString(buffer);
|
||||
#endif
|
||||
DisconnectNamedPipe((HANDLE)fd);
|
||||
rc = (CloseHandle((HANDLE)fd) ? 0 : -1);
|
||||
#ifdef DEBUG_MONITOR
|
||||
sprintf(buffer, "Closed %i\n", fd);
|
||||
OutputDebugString(buffer);
|
||||
#endif
|
||||
return (rc ? GetLastError() : 0);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -102,6 +173,7 @@ JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_SpawnerOutputStream_wr
|
|||
BYTE tmpBuf[BUFF_SIZE];
|
||||
int nBuffOffset = 0;
|
||||
|
||||
|
||||
while(len > nBuffOffset)
|
||||
{
|
||||
int nNumberOfBytesToWrite = min(len - nBuffOffset, BUFF_SIZE);
|
||||
|
@ -139,5 +211,17 @@ JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_SpawnerOutputStream_wr
|
|||
JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_SpawnerOutputStream_close0
|
||||
(JNIEnv * env, jobject proc, jint fd)
|
||||
{
|
||||
return (CloseHandle((HANDLE)fd) ? 0 : -1);
|
||||
int rc;
|
||||
#ifdef DEBUG_MONITOR
|
||||
char buffer[1000];
|
||||
sprintf(buffer, "Close %i\n", fd);
|
||||
OutputDebugString(buffer);
|
||||
#endif
|
||||
DisconnectNamedPipe((HANDLE)fd);
|
||||
rc = (CloseHandle((HANDLE)fd) ? 0 : -1);
|
||||
#ifdef DEBUG_MONITOR
|
||||
sprintf(buffer, "Closed %i\n", fd);
|
||||
OutputDebugString(buffer);
|
||||
#endif
|
||||
return (rc ? GetLastError() : 0);
|
||||
}
|
||||
|
|
|
@ -1,16 +1,17 @@
|
|||
/**********************************************************************
|
||||
* Copyright (c) 2002,2003 QNX Software Systems and others.
|
||||
* Copyright (c) 2002-2004 QNX Software Systems and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v0.5
|
||||
* are made available under the terms of the Common Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v05.html
|
||||
* http://www.eclipse.org/legal/cpl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* QNX Software Systems - Initial API and implementation
|
||||
*
|
||||
* raise.c
|
||||
*
|
||||
* This is a part of JNI implementation of spawner
|
||||
***********************************************************************/
|
||||
/*
|
||||
* This is a JNI implementation of spawner
|
||||
*/
|
||||
#include "stdafx.h"
|
||||
#include "Spawner.h"
|
||||
|
||||
|
@ -19,10 +20,17 @@
|
|||
|
||||
extern void JNICALL ThrowByName(JNIEnv *env, const char *name, const char *msg);
|
||||
|
||||
// #define DEBUG_MONITOR
|
||||
|
||||
static HWND consoleHWND;
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
// Check if window is a console of process with pid
|
||||
// Arguments:
|
||||
// hwnd - window handler
|
||||
// arg - process PID
|
||||
// Return : TRUE if yes
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
static BOOL CALLBACK
|
||||
find_child_console (HWND hwnd, LPARAM arg)
|
||||
{
|
||||
|
@ -46,35 +54,13 @@ find_child_console (HWND hwnd, LPARAM arg)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_raise__Ljava_lang_Object_2
|
||||
(JNIEnv * env, jobject process, jobject jpid)
|
||||
{
|
||||
jint pid;
|
||||
jclass integerClass = (*env) -> FindClass(env, "java/lang/Integer");
|
||||
jmethodID intValue;
|
||||
if(NULL == integerClass) {
|
||||
ThrowByName(env, "java/lang/IOException", "Cannot find Integer class");
|
||||
return -1;
|
||||
}
|
||||
if(!((*env) -> IsInstanceOf(env, jpid, integerClass))) {
|
||||
ThrowByName(env, "java/lang/IOException", "Wrong argument");
|
||||
return -1;
|
||||
}
|
||||
|
||||
intValue = (*env) -> GetMethodID(env, integerClass, "intValue", "()I");
|
||||
if(NULL == intValue) {
|
||||
ThrowByName(env, "java/lang/IOException", "Cannot find intValue method in Integer class");
|
||||
return -1;
|
||||
}
|
||||
|
||||
pid = (*env) -> CallIntMethod(env, jpid, intValue);
|
||||
|
||||
return interruptProcess(pid);
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
// Function implements interrupt process (Ctrl-C emulation)
|
||||
// Arguments:
|
||||
// pid - process' pid
|
||||
// Return : 0 if OK or error code
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
int interruptProcess(int pid)
|
||||
{
|
||||
#ifdef DEBUG_MONITOR
|
||||
|
@ -89,10 +75,13 @@ int interruptProcess(int pid)
|
|||
sprintf(buffer, "Try to interrupt process %i\n", pid);
|
||||
OutputDebugString(buffer);
|
||||
#endif
|
||||
// Find console
|
||||
EnumWindows (find_child_console, (LPARAM) pid);
|
||||
|
||||
if(NULL != consoleHWND)
|
||||
if(NULL != consoleHWND) // Yes, we found out it
|
||||
{
|
||||
// We are going to switch focus to console,
|
||||
// send Ctrl-C and then restore focus
|
||||
BYTE control_scan_code = (BYTE) MapVirtualKey (VK_CONTROL, 0);
|
||||
/* Fake Ctrl-C for SIGINT, and Ctrl-Break for SIGQUIT. */
|
||||
BYTE vk_c_code = 'C';
|
||||
|
@ -100,7 +89,7 @@ int interruptProcess(int pid)
|
|||
BYTE c_scan_code = (BYTE) MapVirtualKey (vk_c_code, 0);
|
||||
BYTE break_scan_code = (BYTE) MapVirtualKey (vk_break_code, 0);
|
||||
HWND foreground_window;
|
||||
|
||||
|
||||
|
||||
foreground_window = GetForegroundWindow ();
|
||||
if (foreground_window)
|
||||
|
@ -128,17 +117,6 @@ int interruptProcess(int pid)
|
|||
/* Set the foreground window to the child. */
|
||||
if (SetForegroundWindow (consoleHWND))
|
||||
{
|
||||
/*
|
||||
if(0 != c_scan_code) {
|
||||
// Generate keystrokes as if user had typed Ctrl-C.
|
||||
keybd_event (VK_CONTROL, control_scan_code, 0, 0);
|
||||
keybd_event (vk_c_code, c_scan_code, 0, 0);
|
||||
keybd_event (vk_c_code, c_scan_code, KEYEVENTF_KEYUP, 0);
|
||||
keybd_event (VK_CONTROL, control_scan_code, KEYEVENTF_KEYUP, 0);
|
||||
}
|
||||
*/
|
||||
/* Sleep for a bit to give time for respond */
|
||||
Sleep (100);
|
||||
if(0 != break_scan_code) {
|
||||
/* Generate keystrokes as if user had typed Ctrl-Break */
|
||||
keybd_event (VK_CONTROL, control_scan_code, 0, 0);
|
||||
|
|
|
@ -1,22 +1,26 @@
|
|||
/**********************************************************************
|
||||
* Copyright (c) 2002,2003 QNX Software Systems and others.
|
||||
* Copyright (c) 2002-2004 QNX Software Systems and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v0.5
|
||||
* are made available under the terms of the Common Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v05.html
|
||||
* http://www.eclipse.org/legal/cpl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* QNX Software Systems - Initial API and implementation
|
||||
*
|
||||
* spawner.c
|
||||
*
|
||||
* This is a part of JNI implementation of spawner
|
||||
***********************************************************************/
|
||||
// spawner.cpp : Defines the entry point for the DLL application.
|
||||
//
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "spawner.h"
|
||||
|
||||
|
||||
CRITICAL_SECTION cs;
|
||||
|
||||
TCHAR path[MAX_PATH + 1] = {_T('\0') };
|
||||
|
||||
TCHAR path[MAX_PATH + 1] = {_T('\0') }; // Directory where spawner.dll is located
|
||||
|
||||
|
||||
BOOL APIENTRY DllMain( HANDLE hModule,
|
||||
|
@ -48,4 +52,3 @@ BOOL APIENTRY DllMain( HANDLE hModule,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,22 +1,19 @@
|
|||
/**********************************************************************
|
||||
* Copyright (c) 2002,2003 QNX Software Systems and others.
|
||||
* Copyright (c) 2002-2004 QNX Software Systems and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v0.5
|
||||
* are made available under the terms of the Common Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v05.html
|
||||
* http://www.eclipse.org/legal/cpl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* QNX Software Systems - Initial API and implementation
|
||||
***********************************************************************/
|
||||
/*
|
||||
* starter.c
|
||||
*
|
||||
* starter.cpp
|
||||
*
|
||||
* This is a small utility for windows spawner
|
||||
*/
|
||||
***********************************************************************/
|
||||
|
||||
|
||||
//#define UNICODE
|
||||
//#define _UNICODE
|
||||
|
||||
#define STRICT
|
||||
#include <Windows.h>
|
||||
|
@ -24,8 +21,9 @@
|
|||
#include <tchar.h>
|
||||
#include <stdio.h>
|
||||
|
||||
// #define DEBUG_MONITOR
|
||||
//#define DEBUG_MONITOR
|
||||
#define MAX_CMD_LINE_LENGTH (2049)
|
||||
#define PIPE_NAME_LENGTH 100
|
||||
|
||||
int copyTo(char * target, const char * source, int cpyLength, int availSpace);
|
||||
|
||||
|
@ -58,8 +56,8 @@ BOOL WINAPI HandlerRoutine( DWORD dwCtrlType) // control signal type
|
|||
|
||||
extern "C" int _tmain(int argc, TCHAR* argv[]) {
|
||||
|
||||
// Make sure that we've been passed the right number of arguments
|
||||
if (argc < 5) {
|
||||
// Make sure that we've been passed the right number of arguments
|
||||
if (argc < 7) {
|
||||
_tprintf(__TEXT("Usage: %s (Three InheritableEventHandles) (CommandLineToSpawn)\n"),
|
||||
argv[0]);
|
||||
return(0);
|
||||
|
@ -69,7 +67,7 @@ extern "C" int _tmain(int argc, TCHAR* argv[]) {
|
|||
TCHAR szCmdLine[MAX_CMD_LINE_LENGTH] = { 0 };
|
||||
int nPos = 0;
|
||||
|
||||
for(int i = 4; i < argc; ++i)
|
||||
for(int i = 6; i < argc; ++i)
|
||||
{
|
||||
int nCpyLen;
|
||||
if(0 > (nCpyLen = copyTo(szCmdLine + nPos, argv[i], _tcslen(argv[i]), MAX_CMD_LINE_LENGTH - nPos)))
|
||||
|
@ -94,28 +92,81 @@ extern "C" int _tmain(int argc, TCHAR* argv[]) {
|
|||
#endif
|
||||
|
||||
BOOL exitProc = FALSE;
|
||||
HANDLE waitEvent = OpenEvent(EVENT_ALL_ACCESS, TRUE, argv[2]);
|
||||
HANDLE waitEvent = OpenEvent(EVENT_ALL_ACCESS, TRUE, argv[4]);
|
||||
HANDLE h[3];
|
||||
h[0] = OpenEvent(EVENT_ALL_ACCESS, TRUE, argv[1]);
|
||||
h[2] = OpenEvent(EVENT_ALL_ACCESS, TRUE, argv[3]); // This is a terminate event
|
||||
h[0] = OpenEvent(EVENT_ALL_ACCESS, TRUE, argv[3]);
|
||||
h[2] = OpenEvent(EVENT_ALL_ACCESS, TRUE, argv[5]); // This is a terminate event
|
||||
SetConsoleCtrlHandler(HandlerRoutine, TRUE);
|
||||
|
||||
|
||||
int parentPid = strtol(argv[1], NULL, 10);
|
||||
int nCounter = strtol(argv[2], NULL, 10);
|
||||
char inPipeName[PIPE_NAME_LENGTH];
|
||||
char outPipeName[PIPE_NAME_LENGTH];
|
||||
char errPipeName[PIPE_NAME_LENGTH];
|
||||
|
||||
sprintf(inPipeName, "\\\\.\\pipe\\stdin%08i%010i", parentPid, nCounter);
|
||||
sprintf(outPipeName, "\\\\.\\pipe\\stdout%08i%010i", parentPid, nCounter);
|
||||
sprintf(errPipeName, "\\\\.\\pipe\\stderr%08i%010i", parentPid, nCounter);
|
||||
#ifdef DEBUG_MONITOR
|
||||
sprintf(buffer, "starter start command: %s\n", szCmdLine);
|
||||
sprintf(buffer, "Pipes: %s, %s, %s\n", inPipeName, outPipeName, errPipeName);
|
||||
OutputDebugString(buffer);
|
||||
#endif
|
||||
|
||||
HANDLE stdHandles[3];
|
||||
|
||||
SECURITY_ATTRIBUTES sa;
|
||||
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||
sa.bInheritHandle = TRUE;
|
||||
sa.lpSecurityDescriptor = NULL;
|
||||
|
||||
if((INVALID_HANDLE_VALUE == (stdHandles[0] = CreateFile(inPipeName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, &sa))) ||
|
||||
(INVALID_HANDLE_VALUE == (stdHandles[1] = CreateFile(outPipeName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, &sa))) ||
|
||||
(INVALID_HANDLE_VALUE == (stdHandles[2] = CreateFile(errPipeName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, &sa))))
|
||||
{
|
||||
#ifdef DEBUG_MONITOR
|
||||
sprintf(buffer, "Failed to open pipe %i, %i, %i: %i\n", stdHandles[0], stdHandles[1], stdHandles[2], GetLastError());
|
||||
OutputDebugString(buffer);
|
||||
#endif
|
||||
CloseHandle(stdHandles[0]);
|
||||
CloseHandle(stdHandles[1]);
|
||||
CloseHandle(stdHandles[2]);
|
||||
return -1;;
|
||||
}
|
||||
SetHandleInformation(stdHandles[0], HANDLE_FLAG_INHERIT, TRUE);
|
||||
SetHandleInformation(stdHandles[1], HANDLE_FLAG_INHERIT, TRUE);
|
||||
SetHandleInformation(stdHandles[2], HANDLE_FLAG_INHERIT, TRUE);
|
||||
|
||||
if(!SetStdHandle(STD_INPUT_HANDLE, stdHandles[0]) ||
|
||||
!SetStdHandle(STD_OUTPUT_HANDLE, stdHandles[1]) ||
|
||||
!SetStdHandle(STD_ERROR_HANDLE, stdHandles[2])) {
|
||||
#ifdef DEBUG_MONITOR
|
||||
sprintf(buffer, "Failed to reassign standard streams: %i\n", GetLastError());
|
||||
OutputDebugString(buffer);
|
||||
#endif
|
||||
CloseHandle(stdHandles[0]);
|
||||
CloseHandle(stdHandles[1]);
|
||||
CloseHandle(stdHandles[2]);
|
||||
return -1;;
|
||||
}
|
||||
|
||||
|
||||
// OutputDebugString(szCmdLine);
|
||||
// Spawn the other processes as part of this Process Group
|
||||
BOOL f = CreateProcess(NULL, szCmdLine, NULL, NULL, TRUE,
|
||||
0, NULL, NULL, &si, &pi);
|
||||
|
||||
// We don't need them any more
|
||||
CloseHandle(stdHandles[0]);
|
||||
CloseHandle(stdHandles[1]);
|
||||
CloseHandle(stdHandles[2]);
|
||||
if (f)
|
||||
{
|
||||
#ifdef DEBUG_MONITOR
|
||||
sprintf(buffer, "Process %i started\n", pi.dwProcessId);
|
||||
OutputDebugString(buffer);
|
||||
#endif
|
||||
SetEvent(waitEvent); // Means thar process has been spawned
|
||||
CloseHandle(pi.hThread);
|
||||
h[1] = pi.hProcess;
|
||||
|
||||
while(!exitProc)
|
||||
{
|
||||
// Wait for the spawned-process to die or for the event
|
||||
|
@ -151,6 +202,7 @@ extern "C" int _tmain(int argc, TCHAR* argv[]) {
|
|||
break;
|
||||
default:
|
||||
// Unexpected code
|
||||
#ifdef DEBUG_MONITOR
|
||||
LPTSTR lpMsgBuf;
|
||||
|
||||
FormatMessage(
|
||||
|
@ -167,6 +219,7 @@ extern "C" int _tmain(int argc, TCHAR* argv[]) {
|
|||
OutputDebugString(lpMsgBuf);
|
||||
// Free the buffer.
|
||||
LocalFree( lpMsgBuf );
|
||||
#endif
|
||||
exitProc = TRUE;
|
||||
break;
|
||||
}
|
||||
|
@ -177,12 +230,21 @@ extern "C" int _tmain(int argc, TCHAR* argv[]) {
|
|||
|
||||
CloseHandle(waitEvent);
|
||||
CloseHandle(h[0]);
|
||||
CloseHandle(h[1]);
|
||||
CloseHandle(h[2]);
|
||||
|
||||
return(dwExitCode);
|
||||
}
|
||||
|
||||
// Return number of bytes in target or -1 in case of error
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
// Use this utility program to process correctly quotation marks in the command line
|
||||
// Arguments:
|
||||
// target - string to copy to
|
||||
// source - string to copy from
|
||||
// cpyLength - copy length
|
||||
// availSpace - size of the target buffer
|
||||
// Return :number of bytes used in target, or -1 in case of error
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
int copyTo(LPTSTR target, LPCTSTR source, int cpyLength, int availSpace)
|
||||
{
|
||||
BOOL bSlash = FALSE;
|
||||
|
|
Binary file not shown.
Binary file not shown.
Loading…
Add table
Reference in a new issue