int LLProcessLauncher::launch(void)
{
	// If there was already a process associated with this object, kill it.
	kill();
	orphan();

	int result = 0;
	
	PROCESS_INFORMATION pinfo;
	STARTUPINFOA sinfo;
	memset(&sinfo, 0, sizeof(sinfo));
	
	std::string args = mExecutable;
	for(int i = 0; i < (int)mLaunchArguments.size(); i++)
	{
		args += " ";
		args += mLaunchArguments[i];
	}
	
	// So retarded.  Windows requires that the second parameter to CreateProcessA be a writable (non-const) string...
	char *args2 = new char[args.size() + 1];
	strcpy(args2, args.c_str());

	if( ! CreateProcessA( NULL, args2, NULL, NULL, FALSE, 0, NULL, NULL, &sinfo, &pinfo ) )
	{
		// TODO: do better than returning the OS-specific error code on failure...
		result = GetLastError();
		if(result == 0)
		{
			// Make absolutely certain we return a non-zero value on failure.
			result = -1;
		}
	}
	else
	{
		// foo = pinfo.dwProcessId; // get your pid here if you want to use it later on
		// CloseHandle(pinfo.hProcess); // stops leaks - nothing else
		mProcessHandle = pinfo.hProcess;
		CloseHandle(pinfo.hThread); // stops leaks - nothing else
	}		
	
	delete[] args2;
	
	return result;
}
int LLProcessLauncher::launch(void)
{
	// If there was already a process associated with this object, kill it.
	kill();
	orphan();
	
	int result = 0;
	int current_wd = -1;
	
	// create an argv vector for the child process
	const char ** fake_argv = new const char *[mLaunchArguments.size() + 2];  // 1 for the executable path, 1 for the NULL terminator

	int i = 0;
	
	// add the executable path
	fake_argv[i++] = mExecutable.c_str();
	
	// and any arguments
	for(int j=0; j < mLaunchArguments.size(); j++)
		fake_argv[i++] = mLaunchArguments[j].c_str();
	
	// terminate with a null pointer
	fake_argv[i] = NULL;
	
	if(!mWorkingDir.empty())
	{
		// save the current working directory
		current_wd = ::open(".", O_RDONLY);
	
		// and change to the one the child will be executed in
		if (::chdir(mWorkingDir.c_str()))
		{
			// chdir failed
		}
	}
		
 	// flush all buffers before the child inherits them
 	::fflush(NULL);

	pid_t id = vfork();
	if(id == 0)
	{
		// child process
		
		::execv(mExecutable.c_str(), (char * const *)fake_argv);
		
		// If we reach this point, the exec failed.
		// Use _exit() instead of exit() per the vfork man page.
		_exit(0);
	}

	// parent process
	
	if(current_wd >= 0)
	{
		// restore the previous working directory
		if (::fchdir(current_wd))
		{
			// chdir failed
		}
		::close(current_wd);
	}
	
	delete[] fake_argv;
	
	mProcessID = id;
	
	// At this point, the child process will have been created (since that's how vfork works -- the child borrowed our execution context until it forked)
	// If the process doesn't exist at this point, the exec failed.
	if(!isRunning())
	{
		result = -1;
	}
	
	return result;
}
Ejemplo n.º 3
0
int LLProcessLauncher::launch(void)
{
	// If there was already a process associated with this object, kill it.
	kill();
	orphan();

	int result = 0;
	
	PROCESS_INFORMATION pinfo;
	STARTUPINFOA sinfo;
	memset(&sinfo, 0, sizeof(sinfo));
	
	std::string args = mExecutable;
	for(int i = 0; i < (int)mLaunchArguments.size(); i++)
	{
		args += " ";
		args += mLaunchArguments[i];
	}
	
	// So retarded.  Windows requires that the second parameter to CreateProcessA be a writable (non-const) string...
	char *args2 = new char[args.size() + 1];
	strcpy(args2, args.c_str());

	const char * working_directory = 0;
	if(!mWorkingDir.empty()) working_directory = mWorkingDir.c_str();
	if( ! CreateProcessA( NULL, args2, NULL, NULL, FALSE, 0, NULL, working_directory, &sinfo, &pinfo ) )
	{
		result = GetLastError();

		LPTSTR error_str = 0;
		if(
			FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
				NULL,
				result,
				0,
				(LPTSTR)&error_str,
				0,
				NULL) 
			!= 0) 
		{
			char message[256];
			wcstombs(message, error_str, 256);
			message[255] = 0;
			LL_WARNS() << "CreateProcessA failed: " << message << LL_ENDL;
			LocalFree(error_str);
		}

		if(result == 0)
		{
			// Make absolutely certain we return a non-zero value on failure.
			result = -1;
		}
	}
	else
	{
		// foo = pinfo.dwProcessId; // get your pid here if you want to use it later on
		// CloseHandle(pinfo.hProcess); // stops leaks - nothing else
		mProcessHandle = pinfo.hProcess;
		CloseHandle(pinfo.hThread); // stops leaks - nothing else
	}		
	
	delete[] args2;
	
	return result;
}
Ejemplo n.º 4
0
void pTextEdit::setWordWrap(bool wordWrap) {
  //ES_AUTOHSCROLL cannot be changed after widget creation.
  //As a result, we must destroy and re-create widget to change this setting.
  orphan();
}
Ejemplo n.º 5
0
int LLProcessLauncher::launch(void)
{
	// If there was already a process associated with this object, kill it.
	kill();
	orphan();
	
	int result = 0;
	int current_wd = -1;
	
	// create an argv vector for the child process
	const char ** fake_argv = new const char *[mLaunchArguments.size() + 2];  // 1 for the executable path, 1 for the NULL terminator

	int i = 0;
	
	// add the executable path
	fake_argv[i++] = mExecutable.c_str();
	
	// and any arguments
	for(int j=0; j < mLaunchArguments.size(); j++)
		fake_argv[i++] = mLaunchArguments[j].c_str();
	
	// terminate with a null pointer
	fake_argv[i] = NULL;
	
	if(!mWorkingDir.empty())
	{
		// save the current working directory
		current_wd = ::open(".", O_RDONLY);
	
		// and change to the one the child will be executed in
		if (::chdir(mWorkingDir.c_str()))
		{
			// chdir failed
		}
	}
		
	pid_t id;
	{
#ifdef DEBUG_PIPE_CHILD_ERROR_REPORTING
		// Set up a pipe to the child process for error reporting.
		apr_file_t* in;
		apr_file_t* out;
		LLAPRPool pool;
		pool.create();
#if(APR_VERSION_MAJOR==1 && APR_VERSION_MINOR>=3 || APR_VERSION_MAJOR>1)
		apr_status_t status = apr_file_pipe_create_ex(&in, &out, APR_FULL_BLOCK, pool());
#else
		apr_status_t status = apr_file_pipe_create(&in, &out, pool());
#endif
		assert(status == APR_SUCCESS);
		bool success = (status == APR_SUCCESS);
		if (success)
		{
			apr_interval_time_t const timeout = 10000000;	// 10 seconds.
			status = apr_file_pipe_timeout_set(in, timeout);
			assert(status == APR_SUCCESS);
			success = (status == APR_SUCCESS);
		}
#endif // DEBUG_PIPE_CHILD_ERROR_REPORTING

		// flush all buffers before the child inherits them
		::fflush(NULL);

		id = vfork();
		if (id == 0)
		{
			// child process

#ifdef DEBUG_PIPE_CHILD_ERROR_REPORTING
			// Tell parent process we're about to call execv.
			write_pipe(out, "CALLING EXECV");
#ifdef _DEBUG
			char const* display = getenv("DISPLAY");
			std::cerr << "Calling ::execv(\"" << mExecutable << '"';
			for(int j = 0; j < i; ++j)
              std::cerr << ", \"" << fake_argv[j] << '"';
			std::cerr << ") with DISPLAY=\"" << (display ? display : "NULL") << '"' << std::endl;
#endif
#endif // DEBUG_PIPE_CHILD_ERROR_REPORTING

			::execv(mExecutable.c_str(), (char * const *)fake_argv);

#ifdef DEBUG_PIPE_CHILD_ERROR_REPORTING
			status = APR_FROM_OS_ERROR(apr_get_os_error());
			char message[256];
			char errbuf[128];
			apr_strerror(status, errbuf, sizeof(errbuf));
			snprintf(message, sizeof(message), "Child process: execv: %s: %s", mExecutable.c_str(), errbuf);
			write_pipe(out, message);
#ifdef _DEBUG
			std::cerr << "::execv() failed." << std::endl;
#endif
#endif // DEBUG_PIPE_CHILD_ERROR_REPORTING

			// If we reach this point, the exec failed.
			// Use _exit() instead of exit() per the vfork man page.
			_exit(0);
		}

		// parent process

#ifdef DEBUG_PIPE_CHILD_ERROR_REPORTING
		// Close unused pipe end.
		apr_file_close(out);

		if (success)
		{
			// Attempt to do error reporting.
			std::string message = read_pipe(in);
			success = (message == "CALLING EXECV");
			assert(success);
			if (success)
			{
				status = apr_file_pipe_timeout_set(in, 2000000);	// Only wait 2 seconds.
				message = read_pipe(in, true);
				if (message != "TIMEOUT" && message != "END OF FILE")
				{
					// Most likely execv failed.
					llwarns << message << llendl;
					assert(false);	// Fail in debug mode.
				}
			}
		}

		// Clean up.
		apr_file_close(in);
#endif // DEBUG_PIPE_CHILD_ERROR_REPORTING

	}

	if(current_wd >= 0)
	{
		// restore the previous working directory
		if (::fchdir(current_wd))
		{
			// chdir failed
		}
		::close(current_wd);
	}
	
	delete[] fake_argv;
	
	mProcessID = id;
	
	// At this point, the child process will have been created (since that's how vfork works -- the child borrowed our execution context until it forked)
	// If the process doesn't exist at this point, the exec failed.
	if(!isRunning())
	{
		result = -1;
	}
	
	return result;
}