OJInt32_t WindowsProcess::join(OJInt32_t time)
{
    if (isRunning())
        WaitForSingleObject(processHandle_, time); 

    return getExitCode();
}
Esempio n. 2
0
STDMETHODIMP ProcessWrap::COMGETTER(ExitCode)(LONG *aExitCode)
{
    LogRelFlow(("{%p} %s: enter aExitCode=%p\n", this, "Process::getExitCode", aExitCode));

    VirtualBoxBase::clearError();

    HRESULT hrc;

    try
    {
        CheckComArgOutPointerValidThrow(aExitCode);

        AutoCaller autoCaller(this);
        if (FAILED(autoCaller.rc()))
            throw autoCaller.rc();

        hrc = getExitCode(aExitCode);
    }
    catch (HRESULT hrc2)
    {
        hrc = hrc2;
    }
    catch (...)
    {
        hrc = VirtualBoxBase::handleUnexpectedExceptions(this, RT_SRC_POS);
    }

    LogRelFlow(("{%p} %s: leave *aExitCode=%RI32 hrc=%Rhrc\n", this, "Process::getExitCode", *aExitCode, hrc));
    return hrc;
}
OJInt32_t WindowsProcess::start()
{
    ILogger *logger = LoggerFactory::getLogger(LoggerId::AppInitLoggerId);

    //加到作业中
	if (!jobHandle_.assinProcess(processHandle_))
    {
        logger->logErrorX(OJStr("[process] - can't assign process to job! error:%u"), GetLastError());
        kill();
        return -1;
    }

    //启动线程
    ResumeThread(threadHandle_);
    
    //关闭不使用的句柄。让进程执行完毕后立即退出。
    SAFE_CLOSE_HANDLE_AND_RESET(threadHandle_);
    SAFE_CLOSE_HANDLE_AND_RESET(inputFileHandle_)
    SAFE_CLOSE_HANDLE_AND_RESET(outputFileHandle_)

    result_ = AppConfig::JudgeCode::Accept;

	DWORD ExecuteResult = -1;  
	ULONG completeKey;  
	LPOVERLAPPED processInfo;  
	bool done = false;  
	while(!done)  
	{
        if(!jobHandle_.getState(ExecuteResult, completeKey, processInfo))
        {
            DEBUG_MSG(OJStr("get job State faild!"));
            OJSleep(1);
            continue;
        }

        DWORD dwCode = (DWORD)processInfo;

		switch (ExecuteResult)   
		{  
		case JOB_OBJECT_MSG_NEW_PROCESS:    
            //DEBUG_MSG_VS(OJStr("[WindowsProcess]new process: %u"), dwCode);
			break;

		case JOB_OBJECT_MSG_END_OF_JOB_TIME: //job超时
            DEBUG_MSG(OJStr("[WindowsProcess]Job time limit reached")); 
            result_ = AppConfig::JudgeCode::TimeLimitExceed;  
			done = true;  
			break;

		case JOB_OBJECT_MSG_END_OF_PROCESS_TIME:   //线程超时
			DEBUG_MSG(OJStr("[WindowsProcess]process time limit reached"));
            result_ = AppConfig::JudgeCode::TimeLimitExceed;
			done = true;  
			break;

		case JOB_OBJECT_MSG_PROCESS_MEMORY_LIMIT:   //进程内存超限
            DEBUG_MSG(OJStr("[WindowsProcess]Process exceeded memory limit"));  
            result_ = AppConfig::JudgeCode::MemoryLimitExceed;  
			done = true;  
			break;

        case JOB_OBJECT_MSG_JOB_MEMORY_LIMIT: //job内存超限
            {
                OJInt32_t mem = getRunMemory();  
                DebugMessage(OJStr("[WindowsProcess]exceeded job memory limit with %dkb"), mem);
                result_ = AppConfig::JudgeCode::MemoryLimitExceed; 
                done = true;  
            }
			break;  

		case JOB_OBJECT_MSG_ACTIVE_PROCESS_LIMIT:  //超出运行的进程数量
            DEBUG_MSG(OJStr("[WindowsProcess]Too many active processes in job"));
            result_ = AppConfig::JudgeCode::RuntimeError;
            done = true;
			break;

		case JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO:  
            DEBUG_MSG(OJStr("[WindowsProcess]Job contains no active processes")); 
			done = true;  
			break;

		case JOB_OBJECT_MSG_EXIT_PROCESS: //进程退出
            //DEBUG_MSG_VS(OJStr("[WindowsProcess]Process %u exit."), dwCode);
            if(::GetProcessId(processHandle_) == dwCode)
			{
                done = true;
            }
			break;  

		case JOB_OBJECT_MSG_ABNORMAL_EXIT_PROCESS: //进程异常结束
            DEBUG_MSG(OJStr("[WindowsProcess]Process terminated abnormally"));
            result_ = AppConfig::JudgeCode::RuntimeError;  
			done = true;  
			break;  

		default:  
            DEBUG_MSG(OJStr("[WindowsProcess]Unknown notification"));
            result_ = AppConfig::JudgeCode::UnknownError; 
			break;
		}
	}  
    
    {
        FILETIME ftime, temp;
        ::GetProcessTimes(processHandle_, &temp, &temp, &temp, &ftime);

        ULARGE_INTEGER time2;
        time2.LowPart = ftime.dwLowDateTime;
        time2.HighPart = ftime.dwHighDateTime;

        runTime_ = time2.QuadPart / 10000;
    }
    
    {
        PROCESS_MEMORY_COUNTERS info;
        ::GetProcessMemoryInfo(processHandle_, &info, sizeof(info));

        runMemory_ = info.PeakPagefileUsage;
    }

    while(!jobHandle_.terminate())//强制关闭作业
    {
        DEBUG_MSG(OJStr("Terminate job faild!"));
        OJSleep(10);
    }

    alive_ = false;//进程结束

    //正常退出。即不是超时等状况。
    if(result_ == AppConfig::JudgeCode::Accept)
    {
        DWORD code = getExitCode();//获取进程返回值,以判断进程是否执行成功。
        if(code != 0)
        {
            result_ = AppConfig::JudgeCode::RuntimeError;
            DEBUG_MSG_VS(OJStr("process exit with code : %u, last error: %u"), 
                code, GetLastError());
        }
    }

    SAFE_CLOSE_HANDLE_AND_RESET(processHandle_);

	return 0;  
}
Esempio n. 4
0
int MprCmd::start(char *program, char **argv, char **envp, MprCmdProc fn, 
	void *fnData, int userFlags)
{
	char		dir[MPR_MAX_FNAME];
	int			pid, i, err;

	mprAssert(program != 0);
	mprAssert(argv != 0);
	mprLog(4, log, "start: %s\n", program);

	reset();

	flags |= (userFlags & MPR_CMD_USER_FLAGS);

	for (i = 0; argv[i]; i++) {
		mprLog(6, log, "    arg[%d]: %s\n", i, argv[i]);
	}
	if (envp) {
		for (i = 0; envp[i]; i++) {
			mprLog(6, log, "    envp[%d]: %s\n", i, envp[i]);
		}
	}

	if (access(program, X_OK) < 0) {
		mprLog(5, log, "start: can't access %s, errno %d\n", 
			program, mprGetOsError());
		return MPR_ERR_CANT_ACCESS;
	}

	data = fnData;
	cmdDoneProc = fn;
	reapIndex = -1;

	//
	//	Create the child
	//
	pid = vfork();

	if (pid < 0) {
		mprLog(0, log, "Can't fork a new process to run %s\n", program);
		return MPR_ERR_CANT_INITIALIZE;

	} else if (pid == 0) {
		//
		//	Child
		//
		umask(022);
		if (flags & MPR_CMD_NEW_SESSION) {
			setsid();
		}
		if (flags & MPR_CMD_CHDIR) {
			if (cwd) {
				chdir(cwd);
			} else {
				mprGetDirName(dir, sizeof(dir), program);
				chdir(dir);
			}
		}

		//	
		//	FUTURE -- could chroot as a security feature (perhaps cgi-bin)
		//
		if (files.clientFd[MPR_CMD_OUT] >= 0) {
			dup2(files.clientFd[MPR_CMD_OUT], 0);	// Client stdin
		} else {
			close(0);
		}
		if (files.clientFd[MPR_CMD_IN] >= 0) {
			dup2(files.clientFd[MPR_CMD_IN], 1);	// Client stdout
			dup2(files.clientFd[MPR_CMD_IN], 2);	// Client stderr
		} else {
			close(1);
			close(2);
		}

		//
		//	FUTURE -- need to get a better max file limit than this
		//
		for (i = 3; i < 128; i++) {
			close(i);
		}

		if (envp) {
			execve(program, argv, envp);
		} else {
			//
			//	Do this rather than user execv to avoid errors in valgrind
			//
			char	*env[2];
	
			env[0] = "_appweb=1";
			env[1] = 0;
			execve(program, argv, (char**) &env);
		}

		err = errno;
		getcwd(dir, sizeof(dir));
		mprStaticPrintf("Can't exec %s, err %d, cwd %s\n", program, err, dir);
		mprAssert(0);
		exit(-(MPR_ERR_CANT_INITIALIZE));

	} else {

		//
		//	Close the client handles
		//
		for (i = 0; i < MPR_CMD_MAX_FD; i++) {
			if (files.clientFd[i] >= 0) {
				close(files.clientFd[i]);
				files.clientFd[i] = -1;
			}
		}

		data = fnData;
		cmdDoneProc = fn;
		process = (ulong) pid;

		if (flags & MPR_CMD_DETACHED) {
			process = 0;
			return 0;

		} else if (flags & MPR_CMD_WAIT) {
			waitForChild(INT_MAX);
			if (getExitCode() < 0) {
				return MPR_ERR_BAD_STATE;
			}
			return exitStatus;

		} else {
			mprGetMpr()->cmdService->startWatcher();
		}
	}
	return 0;
}
Esempio n. 5
0
int MprCmd::start(char *program, char **argv, char **envp, 
	MprCmdProc completionFn, void *fnData, int userFlags)
{
	PROCESS_INFORMATION	procInfo;
	STARTUPINFO			startInfo;
	char				dirBuf[MPR_MAX_FNAME], *systemRoot;
	char				*envBuf, **ep, *cmdBuf, **ap, *destp, *cp, *dir, *key;
	char				progBuf[MPR_MAX_STRING], *localArgv[2], *saveArg0;
	int					argc, len, inheritFiles;

	mprAssert(program);
	mprAssert(argv);

	reset();

	flags |= (userFlags & MPR_CMD_USER_FLAGS);
	exitStatus = -1;

	mprStrcpy(progBuf, sizeof(progBuf), program);
	progBuf[sizeof(progBuf) - 1] = '\0';
	program = progBuf;

	//
	//	Sanitize the command line (program name only)
	//
	for (cp = program; *cp; cp++) {
		if (*cp == '/') {
			*cp = '\\';
		} else if (*cp == '\r' || *cp == '\n') {
			*cp = ' ';
		}
	}
	if (*program == '"') {
		if ((cp = strrchr(++program, '"')) != 0) {
			*cp = '\0';
		}
	}

	saveArg0 = argv[0];
	if (argv == 0) {
		argv = localArgv;
		argv[1] = 0;
	}
	argv[0] = program;

	//
	//	Determine the command line length and arg count
	//
	argc = 0;
	for (len = 0, ap = argv; *ap; ap++) {
		len += strlen(*ap) + 1 + 2;			// Space and possible quotes
		argc++;
	}
	cmdBuf = (char*) mprMalloc(len + 1);
	cmdBuf[len] = '\0';
	
	//
	//	Add quotes to all args that have spaces in them including "program"
	//
	destp = cmdBuf;
	for (ap = &argv[0]; *ap; ) {
		cp = *ap;
		if ((strchr(cp, ' ') != 0) && cp[0] != '\"') {
			*destp++ = '\"';
			strcpy(destp, cp);
			destp += strlen(cp);
			*destp++ = '\"';
		} else {
			strcpy(destp, cp);
			destp += strlen(cp);
		}
		if (*++ap) {
			*destp++ = ' ';
		}
	}
	*destp = '\0';
	mprAssert((int) strlen(destp) < (len - 1));
	mprAssert(cmdBuf[len] == '\0');
	argv[0] = saveArg0;

	envBuf = 0;
	if (envp) {
		for (len = 0, ep = envp; *ep; ep++) {
			len += strlen(*ep) + 1;
		}

		key = "SYSTEMROOT";
		systemRoot = getenv(key);
		if (systemRoot) {
			len += strlen(key) + 1 + strlen(systemRoot) + 1;
		}

		envBuf = (char*) mprMalloc(len + 2);		// Win requires two nulls
		destp = envBuf;
		for (ep = envp; *ep; ep++) {
			strcpy(destp, *ep);
			mprLog(6, log, "Set CGI variable: %s\n", destp);
			destp += strlen(*ep) + 1;
		}

		strcpy(destp, key);
		destp += strlen(key);
		*destp++ = '=';
		strcpy(destp, systemRoot);
		destp += strlen(systemRoot) + 1;

		*destp++ = '\0';
		*destp++ = '\0';						// WIN requires two nulls
	}
	
	memset(&startInfo, 0, sizeof(startInfo));
	startInfo.cb = sizeof(startInfo);

    startInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
	if (flags & MPR_CMD_SHOW) {
		startInfo.wShowWindow = SW_SHOW;
	} else {
		startInfo.wShowWindow = SW_HIDE;
	}

	//
	//	CMD_OUT is stdin for the client. CMD_IN is stdout for the client
	//
	if (files.clientFd[MPR_CMD_OUT] > 0) {
		startInfo.hStdInput = 
			(HANDLE) _get_osfhandle(files.clientFd[MPR_CMD_OUT]);
	}
	if (files.clientFd[MPR_CMD_IN] > 0) {
		startInfo.hStdOutput = 
			(HANDLE)_get_osfhandle(files.clientFd[MPR_CMD_IN]);
	}
#if UNUSED
	if (files.clientFd[MPR_CMD_ERR] > 0) {
		startInfo.hStdError = 
			(HANDLE) _get_osfhandle(files.clientFd[MPR_CMD_ERR]);
	}
#endif

#if UNUSED
	SECURITY_ATTRIBUTES	secAtt;
	memset(&secAtt, 0, sizeof(secAtt));
	secAtt.nLength = sizeof(SECURITY_ATTRIBUTES);
	secAtt.bInheritHandle = TRUE;
#endif

	if (userFlags & MPR_CMD_CHDIR) {
		if (cwd) {
			dir = cwd;
		} else {
			mprGetDirName(dirBuf, sizeof(dirBuf), argv[0]);
			dir = dirBuf;
		}
	} else {
		dir = 0;
	}

	inheritFiles = (flags & MPR_CMD_STDIO_MADE) ? 1 : 0;
	flags &= ~(MPR_CMD_STDIO_MADE);

	mprLog(5, log, "Running: %s\n", cmdBuf); 

	if (! CreateProcess(0, cmdBuf, 0, 0, inheritFiles, CREATE_NEW_CONSOLE,
			envBuf, dir, &startInfo, &procInfo)) {
		mprError(MPR_L, MPR_LOG, "Can't create process: %s, %d", 
			cmdBuf, mprGetOsError());
		return MPR_ERR_CANT_CREATE;
	}
	process = (int) procInfo.hProcess;

	//
	//	Wait for the child to initialize
	//
	WaitForInputIdle((HANDLE) process, 1000);

	if (procInfo.hThread != 0)  {
		CloseHandle(procInfo.hThread);
	}

	mprFree(cmdBuf);
	mprFree(envBuf);

	cmdDoneProc = completionFn;
	data = fnData;

	if (flags & MPR_CMD_DETACHED) {
		CloseHandle((HANDLE) process);
		process = 0;

	} else if (userFlags & MPR_CMD_WAIT) {
		waitForChild(INT_MAX);
		if (getExitCode() < 0) {
			return MPR_ERR_BAD_STATE;
		}
		return exitStatus;

	} else {
		mprGetMpr()->cmdService->startWatcher();
	}


	return 0;
}