bool Process::Start( int timeout ) { tstring str = m_Executable; str += TXT( " " ); str += Helium::CmdLineDelimiters[0]; str += Worker::Args::Worker; // make our worker wait forever is we were asked to if ( m_Wait ) { str += TXT( " " ); str += Helium::CmdLineDelimiters[0]; str += Worker::Args::Wait; timeout = -1; } STARTUPINFO startupInfo; memset( &startupInfo, 0, sizeof( startupInfo ) ); startupInfo.cb = sizeof( startupInfo ); PROCESS_INFORMATION procInfo; memset( &procInfo, 0, sizeof( procInfo ) ); DWORD flags = 0; #ifdef _DEBUG flags |= CREATE_NEW_CONSOLE; #else flags |= CREATE_NO_WINDOW; #endif // Start the child process. if( !m_Debug && !::CreateProcess( NULL, (LPTSTR) str.c_str(), NULL, NULL, FALSE, flags, NULL, NULL, &startupInfo, &procInfo ) ) { throw Helium::Exception( TXT( "Failed to run '%s' (%s)\n" ), str.c_str(), Helium::GetErrorString().c_str() ); } else { // save this for query later m_Handle = procInfo.hProcess; // create the server side of the connection IPC::PipeConnection* connection = new IPC::PipeConnection (); // init pipe connection with background process' process id (hex) tostringstream stream; if ( m_Debug ) { stream << TXT( "worker_debug" ); } else { stream << TXT( "worker_" ) << std::hex << GetProcessId( m_Handle ); } connection->Initialize(true, TXT( "Worker Process Connection" ), stream.str().c_str()); // setup global connection m_Connection = connection; // release handles to our new process ::CloseHandle( procInfo.hThread ); // mutex from kill Helium::MutexScopeLock mutex ( m_KillMutex ); while ( timeout-- != 0 ) { if ( m_Killed ) { break; } if ( m_Connection && m_Connection->GetState() == IPC::ConnectionStates::Active ) { break; } if ( m_Handle ) { DWORD code = 0x0; ::GetExitCodeProcess( m_Handle, &code ); if ( code != STILL_ACTIVE ) { break; } } Sleep( 1 ); } if ( m_Connection && m_Connection->GetState() != IPC::ConnectionStates::Active ) { Kill(); return false; } return true; } }
bool Process::Start( int timeout ) { std::string str = m_Executable; str += TXT( " " ); str += Helium::CmdLineDelimiters[0]; str += Worker::Args::Worker; // make our worker wait forever is we were asked to if ( m_Wait ) { str += TXT( " " ); str += Helium::CmdLineDelimiters[0]; str += Worker::Args::Wait; timeout = -1; } // Start the child process. if( !m_Debug ) { m_Handle = Spawn( str.c_str() ); if ( m_Handle == 0 ) { throw Helium::Exception( TXT( "Failed to run '%s' (%s)\n" ), str.c_str(), Helium::GetErrorString().c_str() ); } // create the server side of the connection IPC::PipeConnection* connection = new IPC::PipeConnection (); // init pipe connection with background process' process id (hex) std::ostringstream stream; if ( m_Debug ) { stream << TXT( "worker_debug" ); } else { stream << TXT( "worker_" ) << std::hex << GetProcessId( m_Handle ); } connection->Initialize(true, TXT( "Worker Process Connection" ), stream.str().c_str()); // setup global connection m_Connection = connection; // mutex from kill Helium::MutexScopeLock mutex ( m_KillMutex ); while ( timeout-- != 0 ) { if ( m_Killed ) { break; } if ( m_Connection && m_Connection->GetState() == IPC::ConnectionStates::Active ) { break; } if ( m_Handle ) { if ( !SpawnRunning( m_Handle ) ) { break; } } Thread::Yield(); } if ( m_Connection && m_Connection->GetState() != IPC::ConnectionStates::Active ) { Kill(); return false; } return true; } return false; }