Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [cdt-dev] Starter.exe

Hi,

This approach worked for me. I have two different starter.exes -- one for cygwin, one for normal NT. Since I know which invocations are cygwin, it works out.

As a funny aside, one of our engineers here who is the cygwin owner but hates it with a passion seems to be calling me the king of the gross hacks at the same time that he is amazingly pleased that it just works and he did not actually have to do anything. Never underestimate the power of someone's ability to rely on other people doing the dirty work.

No one will likely ever care, but I've put the source code at the end in case anyone comes up against this at some point. Mail archives can be wonderful things once in a while and no one else should have to go through this.

Thanks!
-Chris

/*  cygstarter.c
 *
 *  This is an interface bewtween eclipse's spawner.dll and
 * cygwin applications that correctly converts CTRL_C_EVENT to
 * SIGINT.
 *
 * As a practical matter this only works on windows NT platforms
 * (cygwin has a different pid to dwProessId mapping on non NT
 * platforms) and is only known to work on cygwin 1.1.8-2.
 */


#include <Windows.h>
#include <process.h>
#include <stdio.h>
#include <mingw/tchar.h>
#include <signal.h>

// #define DEBUG_MONITOR
#define MAX_CMD_LINE_LENGTH (1024)

int main(int argc, TCHAR* argv[]) {
   char szCmdLine[MAX_CMD_LINE_LENGTH] = { 0 };
   STARTUPINFO         si = { sizeof(si) };
   PROCESS_INFORMATION pi = { 0 };
   DWORD dwExitCode = 0;
#ifdef DEBUG_MONITOR
   int currentPID = GetCurrentProcessId();
   char buffer[MAX_CMD_LINE_LENGTH];
#endif
   BOOL exitProc = FALSE;
   HANDLE waitEvent;
   HANDLE h[3];
   BOOL f;
   LPTSTR lpMsgBuf;
   int i;

   // Make sure that we've been passed the right number of arguments
   if (argc < 5) {
_tprintf(_TEXT("Usage: %s (Three InheritableEventHandles) (CommandLineToSpawn)\n"),
         argv[0]);
      return(0);
   }

   // Construct the full command line
   for (i = 4; i < argc; i++) {
	  if(sizeof(szCmdLine) > (_tcslen(szCmdLine) + _tcslen(argv[i])))
		{
		_tcscat(szCmdLine, argv[i]);
		_tcscat(szCmdLine, _TEXT(" "));
		}
#ifdef DBUG_MONITOR
	  else
		OutputDebugString("Command line is too long\n");
#endif
   }

   waitEvent = OpenEvent(EVENT_ALL_ACCESS, TRUE, argv[2]);
   h[0] = OpenEvent(EVENT_ALL_ACCESS, TRUE, argv[1]);
h[2] = OpenEvent(EVENT_ALL_ACCESS, TRUE, argv[3]); // This is a terminate event

#ifdef DEBUG_MONITOR
	sprintf(buffer, "starter start command: %s\n", szCmdLine);
	OutputDebugString(buffer);
#endif

//   OutputDebugString(szCmdLine);
   // Spawn the other processes as part of this Process Group
   f = CreateProcess(NULL, szCmdLine, NULL, NULL, TRUE,
      0, NULL, NULL, &si, &pi);

   if (f)
   {
   	  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
		  // indicating that the processes should be forcibly killed.
		  switch (WaitForMultipleObjects(3, h, FALSE, INFINITE))
			{
			 case WAIT_OBJECT_0 + 0:  // Send Ctrl-C
#ifdef DEBUG_MONITOR
				sprintf(buffer, "starter (PID %i) received CTRL-C event\n", currentPID);
				OutputDebugString(buffer);
#endif
				kill( pi.dwProcessId, SIGINT );
				SetEvent(waitEvent);
				break;

			 case WAIT_OBJECT_0 + 1:  // App terminated normally
				// Make it's exit code our exit code
#ifdef DEBUG_MONITOR
sprintf(buffer, "starter: launched process has been terminated(PID %i)\n", currentPID);
				OutputDebugString(buffer);
#endif
				GetExitCodeProcess(pi.hProcess, &dwExitCode);
				exitProc = TRUE;
				break;
			 case WAIT_OBJECT_0 + 2:  // Kill
#ifdef DEBUG_MONITOR
				sprintf(buffer, "starter received KILL event (PID %i)\n", currentPID);
				OutputDebugString(buffer);
#endif
				kill( pi.dwProcessId, SIGINT );
				TerminateProcess(h[1], 0);
				exitProc = TRUE;
				break;
			 default:
			 // Unexpected code

				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
				);
				OutputDebugString(lpMsgBuf);
				// Free the buffer.
				LocalFree( lpMsgBuf );
				exitProc = TRUE;
				break;
			 }
			
		  }
      CloseHandle(pi.hProcess);
	}

   CloseHandle(waitEvent);
   CloseHandle(h[0]);
   CloseHandle(h[2]);

   return(dwExitCode);
}


//////////////////////////////// End of File //////////////////////////////////



Back to the top