Пример #1
0
static void gracefulShutdown(MprTime timeout)
{
    HWND    hwnd;

    hwnd = FindWindow(BLD_PRODUCT, BLD_NAME);
    if (hwnd) {
        PostMessage(hwnd, WM_QUIT, 0, 0L);

        /*
            Wait for up to ten seconds while the service exits
         */
        while (timeout > 0 && hwnd) {
            mprSleep(100);
            timeout -= 100;
            hwnd = FindWindow(BLD_PRODUCT, BLD_NAME);
            if (hwnd == 0) {
                return;
            }
        }
    }
    if (app->servicePid) {
        TerminateProcess((HANDLE) app->servicePid, MPR_EXIT_GRACEFUL);
        app->servicePid = 0;
    }
}
Пример #2
0
/*
    Callback from httpLogin to verify credentials using the password defined in the database.
 */
static bool verifyUser(HttpStream *stream, cchar *username, cchar *password)
{
    HttpAuth    *auth;
    HttpUser    *user;
    HttpRx      *rx;
    EdiRec      *urec;

    rx = stream->rx;
    auth = rx->route->auth;

    if ((urec = readRecWhere("user", "username", "==", username)) == 0) {
        httpLog(stream->trace, "auth.login.error", "error", "msg: 'Cannot verify user', username: '******'", username);
        return 0;
    }
    if (!mprCheckPassword(password, getField(urec, "password"))) {
        httpLog(stream->trace, "auth.login.error", "error", "msg: 'Password failed to authenticate', username: '******'", username);
        mprSleep(500);
        return 0;
    }
    /*
        Cache the user and define the user roles. Thereafter, the app can use "httpCanUser" to test if the user
        has the required abilities (defined by their roles) to perform a given request or operation.
     */
    if ((user = httpLookupUser(auth, username)) == 0) {
        user = httpAddUser(auth, username, 0, ediGetFieldValue(urec, "roles"));
    }
    /*
        Define this as the authenticated and authorized user for this session
     */
    httpSetStreamUser(stream, user);

    httpLog(stream->trace, "auth.login.authenticated", "context", "msg: 'User authenticated', username: '******'", username);
    return 1;
}
Пример #3
0
/*
    This is called when unloading a view or controller module
 */
bool espUnloadModule(cchar *module, MprTime timeout)
{
    MprModule   *mp;
    MprTime     mark;
    Esp         *esp;

    /* MOB - should this suspend new requests */
    if ((mp = mprLookupModule(module)) != 0) {
        esp = MPR->espService;
        mark = mprGetTime();
        do {
            lock(esp);
            /* Own request will count as 1 */
            if (esp->inUse <= 1) {
                mprUnloadModule(mp);
                unlock(esp);
                return 1;
            }
            unlock(esp);
            mprSleep(10);
            /* Defaults to 10 secs */
        } while (mprGetRemainingTime(mark, timeout) > 0);
    }
    return 0;
}
Пример #4
0
static bool stopService(int cmd)
{
    int     exitCode;

    app->exiting = 1;
    app->serviceStopped = 1;

    gracefulShutdown(10 * 1000);
    if (cmd == SERVICE_CONTROL_SHUTDOWN) {
        return 1;
    }

    /*
        Wakeup service event. This will make it exit.
     */
    SetEvent(app->serviceThreadEvent);

    svcStatus.dwCurrentState = SERVICE_STOP_PENDING;
    tellSCM(svcStatus.dwCurrentState, NO_ERROR, 1000);

    exitCode = 0;
    GetExitCodeThread(app->threadHandle, (ulong*) &exitCode);

    while (exitCode == STILL_ACTIVE) {
        GetExitCodeThread(app->threadHandle, (ulong*) &exitCode);
        mprSleep(100);
        tellSCM(svcStatus.dwCurrentState, NO_ERROR, 125);
    }
    svcStatus.dwCurrentState = SERVICE_STOPPED;
    tellSCM(svcStatus.dwCurrentState, exitCode, 0);
    return 1;
}
Пример #5
0
int Mpr::killMpr()
{
	HWND	hwnd;
	int		i;

	hwnd = FindWindow(getAppName(), getAppTitle());
	if (hwnd) {
		PostMessage(hwnd, WM_QUIT, 0, 0L);

		//
		//	Wait for up to ten seconds while winAppWeb exits
		//
		for (i = 0; hwnd && i < 100; i++) {
			mprSleep(100);
			hwnd = FindWindow(getAppName(), getAppTitle());
		}
		if (hwnd == 0) {
			return 0;
		}

	} else {
		mprError(MPR_L, MPR_USER, "Can't find %s to kill", getAppName());
	}
	return -1;
}
Пример #6
0
int MprWinService::stop(int cmd)
{
	int		exitCode;

	svcStopped++;
	mprGetMpr()->terminate(1);

	if (cmd == SERVICE_CONTROL_SHUTDOWN) {
		return 0;
	}

	SetEvent(waitEvent);
	svcStatus.dwCurrentState = SERVICE_STOP_PENDING;
	tellScm(svcStatus.dwCurrentState, NO_ERROR, 1000);

	exitCode = 0;
	GetExitCodeThread(threadHandle, (ulong*) &exitCode);
	while (exitCode == STILL_ACTIVE) {
		GetExitCodeThread(threadHandle, (ulong*) &exitCode);
		mprSleep(100);
		tellScm(svcStatus.dwCurrentState, NO_ERROR, 125);
	}
	svcStatus.dwCurrentState = SERVICE_STOPPED;
	tellScm(svcStatus.dwCurrentState, exitCode, 0);
	return 0;
}
Пример #7
0
static int windowsServiceOps()
{
	winService = new MprWinService(APPWEB_SERVICE_NAME);
	switch (serviceOp) {
	case MPR_INSTALL_SERVICE:
		char path[MPR_MAX_FNAME], cmd[MPR_MAX_FNAME];
		GetModuleFileName(0, path, sizeof(path));
		mprSprintf(cmd, sizeof(cmd), "\"%s\" %s", path, serviceCmdLine);
		winService->install(APPWEB_SERVICE_DISPLAY, cmd);
		break;

	case MPR_UNINSTALL_SERVICE:
		winService->remove(1);
		break;

	case MPR_GO_SERVICE:
		winService->start();
		//
		//	Give time for service to actually start 
		//
		mprSleep(2000);
		break;

	case MPR_STOP_SERVICE:
		winService->remove(0);
		break;
	}
	if (isService) {
		mprGetMpr()->setService(1);
	}
	return 0;
}
Пример #8
0
/*
    This is called when unloading a view or controller module
    All of ESP must be quiesced.
 */
static bool espUnloadModule(cchar *module, MprTicks timeout)
{
    MprModule   *mp;
    MprTicks    mark;

    if ((mp = mprLookupModule(module)) != 0) {
        mark = mprGetTicks();
        esp->reloading = 1;
        do {
            lock(esp);
            /* Own request will count as 1 */
            if (esp->inUse <= 1) {
                if (mprUnloadModule(mp) < 0) {
                    mprLog("error esp", 0, "Cannot unload module %s", mp->name);
                    unlock(esp);
                }
                esp->reloading = 0;
                unlock(esp);
                return 1;
            }
            unlock(esp);
            mprSleep(10);

        } while (mprGetRemainingTicks(mark, timeout) > 0);
        esp->reloading = 0;
    }
    return 0;
}
Пример #9
0
PUBLIC bool httpConfigure(HttpConfigureProc proc, void *data, MprTicks timeout)
{
    Http        *http;
    MprTicks    mark;

    http = HTTP;
    mark = mprGetTicks();
    if (timeout < 0) {
        timeout = http->serverLimits->requestTimeout;
    } else if (timeout == 0) {
        timeout = MAXINT;
    }
    do {
        lock(http->connections);
        /* Own request will count as 1 */
        if (mprGetListLength(http->connections) == 0) {
            (proc)(data);
            unlock(http->connections);
            return 1;
        }
        unlock(http->connections);
        mprSleep(10);
        /* Defaults to 10 secs */
    } while (mprGetRemainingTicks(mark, timeout) > 0);
    return 0;
}
Пример #10
0
/*
 *  Gracefull shutdown for Appweb
 */
static void shutdownAppweb(int timeout)
{
    HWND    hwnd;

    hwnd = FindWindow(BLD_PRODUCT, BLD_NAME);
    if (hwnd) {
        PostMessage(hwnd, WM_QUIT, 0, 0L);

        /*
         *  Wait for up to ten seconds while the service exits
         */
        while (timeout > 0 && hwnd) {
            mprSleep(mpr, 100);
            timeout -= 100;
            hwnd = FindWindow(BLD_PRODUCT, BLD_NAME);
            if (hwnd == 0) {
                return;
            }
        }
    }
    if (servicePid) {
        TerminateProcess((HANDLE) servicePid, 2);
        servicePid = 0;
    }
}
Пример #11
0
/*
 *  Remove the application service.
 */ 
static int removeService(int removeFromScmDb)
{
    SC_HANDLE   svc, mgr;

    exiting = 1;

    mgr = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
    if (! mgr) {
        mprError(mpr, "Can't open service manager");
        return MPR_ERR_CANT_ACCESS;
    }
    svc = OpenService(mgr, serviceName, SERVICE_ALL_ACCESS);
    if (! svc) {
        CloseServiceHandle(mgr);
        mprError(mpr, "Can't open service");
        return MPR_ERR_CANT_OPEN;
    }

    /*
     *  Gracefull shutdown 
     */
    shutdownAppweb(0);

    if (ControlService(svc, SERVICE_CONTROL_STOP, &svcStatus)) {
        mprSleep(mpr, 500);

        while (QueryServiceStatus(svc, &svcStatus)) {
            if (svcStatus.dwCurrentState == SERVICE_STOP_PENDING) {
                mprSleep(mpr, 250);
            } else {
                break;
            }
        }
        if (svcStatus.dwCurrentState != SERVICE_STOPPED) {
            mprError(mpr, "Can't stop service: %x", GetLastError());
        }
    }
    if (removeFromScmDb && !DeleteService(svc)) {
        mprError(mpr, "Can't delete service: %x", GetLastError());
    }
    CloseServiceHandle(svc);
    CloseServiceHandle(mgr);
    return 0;
}
Пример #12
0
int MprWinService::remove(int removeFromScmDb)
{
	SC_HANDLE	svc, mgr;

	mgr = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
	if (! mgr) {
		mprError(MPR_L, MPR_LOG, "Can't open service manager");
		return MPR_ERR_CANT_ACCESS;
	}
	svc = OpenService(mgr, svcName, SERVICE_ALL_ACCESS);
	if (! svc) {
		CloseServiceHandle(mgr);
		mprError(MPR_L, MPR_LOG, "Can't open service");
		return MPR_ERR_CANT_OPEN;
	}

	//
	//	Stop the application
	//
	mprGetMpr()->killMpr();

	if (ControlService(svc, SERVICE_CONTROL_STOP, &svcStatus)) {
		mprSleep(500);

		while (QueryServiceStatus(svc, &svcStatus)) {
			if (svcStatus.dwCurrentState == SERVICE_STOP_PENDING) {
				mprSleep(250);
			} else {
				break;
			}
		}
		if (svcStatus.dwCurrentState != SERVICE_STOPPED) {
			mprError(MPR_L, MPR_LOG, "Can't stop service: %x", GetLastError());
		}
	}

	if (removeFromScmDb && !DeleteService(svc)) {
		mprError(MPR_L, MPR_LOG, "Can't delete service: %x", GetLastError());
	}

	CloseServiceHandle(svc);
	CloseServiceHandle(mgr);
	return 0;
}
Пример #13
0
void MprLogToFile::logConfig()
{
	Mpr			*mpr;
	time_t		now;
	char		timeText[80];

	mpr = mprGetMpr();

	if (mpr == 0) {
		return;
	}
	now = time(0);
	mprCtime(&now, timeText, sizeof(timeText));

	mprLog(MPR_CONFIG, "Configuration for %s\n", mpr->getAppTitle());
	mprLog(MPR_CONFIG, "--------------------------------------------\n");
	mprLog(MPR_CONFIG, "Host:               %s\n", mpr->getHostName());
	mprLog(MPR_CONFIG, "CPU:                %s\n", mpr->getCpu());
	mprLog(MPR_CONFIG, "OS:                 %s\n", mpr->getOs());
	mprLog(MPR_CONFIG, "Distribution:       %s %s\n", BLD_HOST_DIST,
		BLD_HOST_DIST_VER);
	mprLog(MPR_CONFIG, "OS:                 %s\n", mpr->getOs());
	mprLog(MPR_CONFIG, "Version:            %s.%d\n", mpr->getVersion(), 
		mpr->getBuildNumber());
	mprLog(MPR_CONFIG, "BuildType:          %s\n", mpr->getBuildType());
	mprLog(MPR_CONFIG, "Started at:         %s", timeText);
	mprLog(MPR_CONFIG, "Log rotation count: %d\n", rotationCount);
	mprLog(MPR_CONFIG, "--------------------------------------------\n");

#if BLD_DEBUG
#if BLD_FEATURE_HIRES_TIME
	int64 elapsed = mprGetElapsedTime();
	mprSleep(250);
	elapsed = mprGetElapsedTime();
	mprLog(4, "1 second is   ~%,16Ld cycles\n", elapsed * 4);
#else
	int elapsed = mprGetTime(0);
	mprSleep(250);
	elapsed = mprGetTime(0) - elapsed;
	mprLog(4, "1 second is   ~%,8d cycles\n", elapsed * 4);
#endif
#endif
}
Пример #14
0
int	MaOpenSslSocket::write(char *buf, int len)
{
	int		rc, written, totalWritten;

	if (bio == 0 || ssl == 0 || len <= 0) {
		return -1;
	}

	BIO_clear_retry_flags(bio);

	totalWritten = 0;

	do {
		written = BIO_write(bio, buf, len);

		mprLog(7, "written %d, len %d\n", written, len);

		if (written >= 0) {
			do {
				rc = BIO_flush(bio);
				mprLog(7, "BIO_flush rc %d\n", rc);
				if (rc > 0) {
					//	Success
					break;
				}
				//
				//	Nap to prevent busy waiting.
				//
				mprSleep(10);
			} while (rc <= 0 && BIO_should_retry(bio));

			totalWritten += written;
			buf += written;
			len -= written;
		}

		mprLog(7, "write: len %d, written %d, total %d, should_retry %d\n",
			len, written, totalWritten, BIO_should_retry(bio));

		/*
 		 *	If written is < 0 and an error occurred, then BIO_should_retry
 		 *	will return false.
		 */
	} while (len > 0 && (written > 0 || BIO_should_retry(bio)));

	if (totalWritten <= 0 && BIO_should_retry(bio) == 0) {
		mprLog(7, "connection closed\n");
		/* 
		 *	If totalWritten is not Zero, then we don't return an Error.
		 * 	Next time this function is called, it will return an Error.
		 */
		return -1; // return Error ( connection closed )
	}
	return totalWritten;
}
Пример #15
0
/*
    Remove the application service
 */ 
static bool removeService(int removeFromScmDb)
{
    SC_HANDLE   svc, mgr;

    app->exiting = 1;

    mgr = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
    if (! mgr) {
        mprError("Can't open service manager");
        return 0;
    }
    svc = OpenService(mgr, app->serviceName, SERVICE_ALL_ACCESS);
    if (! svc) {
        CloseServiceHandle(mgr);
        mprError("Can't open service");
        return 0;
    }
    gracefulShutdown(0);

    if (ControlService(svc, SERVICE_CONTROL_STOP, &svcStatus)) {
        mprSleep(500);

        while (QueryServiceStatus(svc, &svcStatus)) {
            if (svcStatus.dwCurrentState == SERVICE_STOP_PENDING) {
                mprSleep(250);
            } else {
                break;
            }
        }
        if (svcStatus.dwCurrentState != SERVICE_STOPPED) {
            mprError("Can't stop service: 0x%x", GetLastError());
        }
    }
    if (removeFromScmDb && !DeleteService(svc)) {
        if (GetLastError() != ERROR_SERVICE_MARKED_FOR_DELETE) {
            mprError("Can't delete service: 0x%x", GetLastError());
        }
    }
    CloseServiceHandle(svc);
    CloseServiceHandle(mgr);
    return 1;
}
Пример #16
0
int MprThreadService::stop(int timeout)
{
	//
	//  Wait until all threads (except main thread) have exited
	//
	while (threads.getNumItems() > 1 && timeout > 0) {
		mprSleep(10);
		timeout -= 10;
	}
	return 0;
}
Пример #17
0
int MprTestSession::runTests(MprTestResult *result)
{
	int				i;
#if BLD_FEATURE_MULTITHREAD
	MprThread		*tp;
#endif

	for (i = 0; i < numThreads; i++) {
		if (sessions[i]->init() < 0) {
			return MPR_ERR_CANT_INITIALIZE;
		}
	}

#if BLD_FEATURE_MULTITHREAD
	//
	//	Now clone this session object for all other threads
	//
	for (i = 1; i < numThreads; i++) {
		char tName[64];
		mprSprintf(tName, sizeof(tName), "test.%d", i);
		tp = new MprThread(runWrapper, MPR_NORMAL_PRIORITY, sessions[i], tName);
		if (tp->start() < 0) {
			break;
		}
	}
#endif
	runWrapper(sessions[0], 0);

#if BLD_FEATURE_MULTITHREAD
	//
	//	Wait for all the threads to complete (simple but effective)
	//
	while (result->getThreadCount() > 1) {
		mprSleep(75);
	}
#endif
	sessions[0]->terminateClasses(result);

#if BLD_FEATURE_MULTITHREAD
	for (i = 1; i < numThreads; i++) {
		sessions[i]->term();
		delete sessions[i];
	}
#endif

	mprFree(sessions);

#if BLD_FEATURE_LOG
	mpr->logService->removeListener(logger);
	delete logger;
#endif
	return 0;
}
Пример #18
0
int MprCmd::waitInner(int timeout)
{
	int		err, status;

	lock();
	if (handle == 0) {
		mprAssert(handle != 0);
		unlock();
		return 0;
	}

	if (timeout) {
		if (WaitForSingleObject((HANDLE) handle, timeout) != WAIT_OBJECT_0) {
			mprAssert(0);
			unlock();
			return MPR_ERR_TIMEOUT;
		}
	}

	do {
		if (GetExitCodeProcess((HANDLE) handle, (ulong*) &status) != 0) {
			if (status != STILL_ACTIVE) {
				mprLog(5, log, 
					"waitInner: pid %d, status %d\n", pid, status);
				exitStatus = status;
				unlock();
				return 0;
			} else {
				mprLog(5, log, 
					"waitInner: pid %d, still active\n", pid);
			}
		} else {
			err = GetLastError();
			mprAssert(0);
			unlock();
			return MPR_ERR_BAD_STATE;
		}
		//
		//	Seems we can wakeup from the wait and there still not be status
		//	pending
		//
		mprSleep(50);
	} while (timeout > 0);

	//	Should never get here 
	unlock();
	return MPR_ERR_TIMEOUT;
}
Пример #19
0
static void testTimeBasics(MprTestGroup *gp)
{
    MprTime     mark, now, remaining, elapsed;

    mark = mprGetTime(gp);
    assert(mark != 0);
    
    remaining = mprGetRemainingTime(gp, mark, 30000);
    assert(0 <= remaining && remaining <= 30000);

    elapsed = mprGetElapsedTime(gp, mark);
    assert(0 <= elapsed && elapsed < 30000);

    mprSleep(gp, 20);
    now = mprGetTime(gp);
    assert(mprCompareTime(mark, now) < 0);
}
Пример #20
0
/*
    Gracefull shutdown for Appweb
 */
static void shutdownAppweb()
{
    HWND    hwnd;
    int     i;

    hwnd = FindWindow(MPR->name, MPR->name);
    if (hwnd) {
        PostMessage(hwnd, WM_QUIT, 0, 0L);
        /*
            Wait for up to ten seconds while the service exits
         */
        for (i = 0; hwnd && i < 100; i++) {
            mprSleep(100);
            hwnd = FindWindow(MPR->name, MPR->name);
        }

    } else {
        mprError("appweb monitor", "Cannot find %s to kill", MPR->name);
        return;
    }
}
Пример #21
0
/*
    Gracefull shutdown for Appweb
 */
static void shutdownAppweb()
{
    HWND    hwnd;
    int     i;

    hwnd = FindWindow(app->serviceWindowName, app->serviceWindowTitle);
    if (hwnd) {
        PostMessage(hwnd, WM_QUIT, 0, 0L);
        /*
            Wait for up to ten seconds while the service exits
         */
        for (i = 0; hwnd && i < 100; i++) {
            mprSleep(100);
            hwnd = FindWindow(app->serviceWindowName, app->serviceWindowTitle);
        }

    } else {
        mprError("Can't find %s to kill", app->serviceWindowTitle);
        return;
    }
}
Пример #22
0
int Mpr::killMpr()
{
	HWND	hwnd;
	int		i;

	hwnd = FindWindow(getAppName(), getAppTitle());
	if (hwnd) {
		PostMessage(hwnd, WM_QUIT, 0, 0L);

		//
		//	Wait for up to ten seconds while winAppweb exits
		//
		for (i = 0; hwnd && i < 100; i++) {
			mprSleep(100);
			hwnd = FindWindow(getAppName(), getAppTitle());
		}
		if (hwnd = 0) {
			return 0;
		}
	}
	return -1;
}
Пример #23
0
MprCmdFiles::~MprCmdFiles()
{
	int		j, i, rc, err;

	for (i = 0; i < MPR_CMD_MAX_FD; i++) {
		if (clientFd[i] >= 0) {
			close(clientFd[i]);
			clientFd[i] = -1;
		}
		if (serverFd[i] >= 0) {
			close(serverFd[i]);
			serverFd[i] = -1;
		}
		if (name[i]) {
			//
			//	Windows seems to be very slow in cleaning up the child's
			//	hold on the standard I/O file descriptors. Despite having
			//	waited for the child to exit and having received exit status,
			//	this unlink sometimes still gets a sharing violation. Ugh !!!
			//	We need to retry here (for up to 60 seconds). Under extreme 
			//	load -- this may fail to unlink the file.
			//
			for (j = 0; j < 1000; j++) {
				rc = unlink(name[i]);
				if (rc == 0) {
					break;
				}
				err = GetLastError();
				mprSleep(60);
			}
			if (j == 1000) {
				mprLog(0, "File busy, failed to unlink %s\n", name[i]);
			}
			mprFree(name[i]);
		}
	}
}
Пример #24
0
/*
 *  Stop the service in the current process. 
 */ 
static int stopService(int cmd)
{
    int     exitCode;

    exiting = 1;
    serviceStopped = 1;

    /*
     *  Gracefull shutdown 
     */
    shutdownAppweb(10 * 1000);

    if (cmd == SERVICE_CONTROL_SHUTDOWN) {
        return 0;
    }

    /*
     *  Wakeup service event. This will make it exit.
     */
    SetEvent(serviceThreadEvent);

    svcStatus.dwCurrentState = SERVICE_STOP_PENDING;
    tellSCM(svcStatus.dwCurrentState, NO_ERROR, 1000);

    exitCode = 0;
    GetExitCodeThread(threadHandle, (ulong*) &exitCode);

    while (exitCode == STILL_ACTIVE) {
        GetExitCodeThread(threadHandle, (ulong*) &exitCode);
        mprSleep(mpr, 100);
        tellSCM(svcStatus.dwCurrentState, NO_ERROR, 125);
    }
    svcStatus.dwCurrentState = SERVICE_STOPPED;
    tellSCM(svcStatus.dwCurrentState, exitCode, 0);
    return 0;
}
Пример #25
0
/*
 *  Collect the child's exit status. The initiating thread must do this on uClibc. 
 *  Return zero if the exit status is successfully reaped. Return -1 if an error 
 *  and return > 0 if process still running.
 */
int mprReapCmd(MprCmd *cmd, int timeout)
{
    MprTime     mark;

    mprAssert(cmd->pid);

    if (timeout < 0) {
        timeout = MAXINT;
    }
    mark = mprGetTime(cmd);

    while (cmd->pid) {
#if BLD_UNIX_LIKE
        int     status, waitrc;
        status = 0;
        if ((waitrc = waitpid(cmd->pid, &status, WNOHANG | __WALL)) < 0) {
            mprAssert(0);
            mprLog(cmd, 0, "waitpid failed for pid %d, errno %d", cmd->pid, errno);
            return MPR_ERR_CANT_READ;

        } else if (waitrc == cmd->pid) {
            if (!WIFSTOPPED(status)) {
                if (WIFEXITED(status)) {
                    cmd->status = WEXITSTATUS(status);
                } else if (WIFSIGNALED(status)) {
                    cmd->status = WTERMSIG(status);
                }
                cmd->pid = 0;
            }
            break;
            
        } else {
            mprAssert(waitrc == 0);
        }
#endif
#if VXWORKS
        /*
         *  The command exit status (cmd->status) is set in cmdTaskEntry
         */
        if (semTake(cmd->exitCond, MPR_TIMEOUT_STOP_TASK) != OK) {
            mprError(cmd, "cmd: child %s did not exit, errno %d", cmd->program);
            return MPR_ERR_CANT_CREATE;
        }
        semDelete(cmd->exitCond);
        cmd->exitCond = 0;
        cmd->pid = 0;
#endif
#if BLD_WIN_LIKE
        int     status, rc;
        if ((rc = WaitForSingleObject(cmd->process, 10)) != WAIT_OBJECT_0) {
            if (rc == WAIT_TIMEOUT) {
                return -MPR_ERR_TIMEOUT;
            }
            mprLog(cmd, 6, "cmd: WaitForSingleObject no child to reap rc %d, %d", rc, GetLastError());
            return MPR_ERR_CANT_READ;
        }
        if (GetExitCodeProcess(cmd->process, (ulong*) &status) == 0) {
            mprLog(cmd, 7, "cmd: GetExitProcess error");
            return MPR_ERR_CANT_READ;
        }
        if (status != STILL_ACTIVE) {
            cmd->status = status;
            CloseHandle(cmd->process);
            CloseHandle(cmd->thread);
            cmd->process = 0;
            cmd->pid = 0;
            break;
        }
#endif
        if (mprGetElapsedTime(cmd, mark) > timeout) {
            break;
        }
        /* Prevent busy waiting */
        mprSleep(cmd, 10);
    }
    return (cmd->pid == 0) ? 0 : 1;
}
Пример #26
0
int APIENTRY WinMain(HINSTANCE inst, HINSTANCE junk, char *args, int junk2)
{
    char    **argv, *argp, *serviceArgs, *homeDir;
    int     argc, err, nextArg, installFlag;

    mpr = mprCreate(0, NULL, NULL);

    appInst = inst;
    serviceArgs = 0;
    err = 0;
    exiting = 0;
    installFlag = 0;
    homeDir = 0;
    heartBeatPeriod = HEART_BEAT_PERIOD;

    initService();

    mprSetAppName(mpr, BLD_PRODUCT "Angel", BLD_NAME "Angel", BLD_VERSION);
    appName = mprGetAppName(mpr);
    appTitle = mprGetAppTitle(mpr);

    mprSetLogHandler(mpr, logHandler, NULL);

    /*
     *  Create the window 
     */
    if (initWindow() < 0) {
        mprError(mpr, "Can't initialize application Window");
        return FALSE;
    }

    /*
     *  Parse command line arguments
     */
    if (mprMakeArgv(mpr, "", args, &argc, &argv) < 0) {
        return FALSE;
    }
    for (nextArg = 1; nextArg < argc; nextArg++) {
        argp = argv[nextArg];
        if (*argp != '-' || strcmp(argp, "--") == 0) {
            break;
        }

        if (strcmp(argp, "--args") == 0) {
            /*
             *  Args to pass to service when it starts
             */
            if (nextArg >= argc) {
                err++;
            } else {
                serviceArgs = argv[++nextArg];
            }

        } else if (strcmp(argp, "--console") == 0) {
            /*
             *  Allow the service to interact with the console
             */
            createConsole++;

        } else if (strcmp(argp, "--daemon") == 0) {
            /* Ignored on windows */

        } else if (strcmp(argp, "--heartBeat") == 0) {
            /*
             *  Set the heart beat period
             */
            if (nextArg >= argc) {
                err++;
            } else {
                heartBeatPeriod = atoi(argv[++nextArg]) * 1000;
            }

        } else if (strcmp(argp, "--home") == 0) {
            /*
             *  Change to this directory before starting the service
             */
            if (nextArg >= argc) {
                err++;
            } else {
                homeDir = argv[++nextArg];
            }

        } else if (strcmp(argp, "--program") == 0) {
            if (nextArg >= argc) {
                err++;
            } else {
                serviceProgram = argv[++nextArg];
            }

        } else if (strcmp(argp, "--install") == 0) {
            installFlag++;

        } else if (strcmp(argp, "--start") == 0) {
            /*
             *  Start the angel
             */
            if (startService() < 0) {
                return FALSE;
            }
            mprSleep(mpr, 2000);    /* Time for service to really start */

        } else if (strcmp(argp, "--stop") == 0) {
            /*
             *  Stop the  angel
             */
            if (removeService(0) < 0) {
                return FALSE;
            }

        } else if (strcmp(argp, "--uninstall") == 0) {
            /*
             *  Remove the  angel
             */
            if (removeService(1) < 0) {
                return FALSE;
            }

        } else if (strcmp(argp, "--verbose") == 0 || strcmp(argp, "-v") == 0) {
            verbose++;

        } else {
            err++;
        }

        if (err) {
            mprUserError(mpr, 
                "Bad command line: %s\n"
                "  Usage: %s [options] [program args]\n"
                "  Switches:\n"
                "    --args               # Args to pass to service\n"
                "    --console            # Display the service console\n"
                "    --heartBeat interval # Heart beat interval period (secs)\n"
                "    --home path          # Home directory for service\n"
                "    --install            # Install the service\n"
                "    --program            # Service program to start\n"
                "    --start              # Start the service\n"
                "    --stop               # Stop the service\n"
                "    --uninstall          # Uninstall the service",
                args, appName);
            return -1;
        }
    }

    if (installFlag) {
        /*
         *  Install the angel
         */
        if (installService(homeDir, serviceArgs) < 0) {
            return FALSE;
        }
    }

    if (argc <= 1) {
        /*
         *  This will block if we are a service and are being started by the
         *  service control manager. While blocked, the svcMain will be called
         *  which becomes the effective main program. 
         */
        startDispatcher(serviceMain);
    }
    return 0;
}
Пример #27
0
int main(int argc, char *argv[])
{
	double			elapsed;
	char			*programName, *argp, *logSpec;
	int				c, errflg, start;
#if BLD_FEATURE_LOG
	MprLogToFile	*logger;
#endif
#if BLD_FEATURE_MULTITHREAD
	MprThread		*threadp;
#endif

	programName = mprGetBaseName(argv[0]);
	method = "GET";
	fileList = cmpDir = writeDir = 0;
	verbose = continueOnErrors = outputHeader = errflg = 0;
	poolThreads = 4;			// Need at least one to run efficiently
	httpVersion = 1;			// HTTP/1.1
	success = 1;
	trace = 0;
	host = "localhost";
	logSpec = "stdout:1";
	postData = 0;
	postLen = 0;
	retries = MPR_HTTP_CLIENT_RETRIES;
	iterations = HTTP_DEFAULT_ITERATIONS;
	loadThreads = HTTP_DEFAULT_LOAD_THREADS;
	timeout = MPR_HTTP_CLIENT_TIMEOUT;

#if BLD_FEATURE_MULTITHREAD
	mutex = new MprMutex();
#endif

	//
	//	FUTURE: switch to GNU style --args with a better usage message
	//
	MprCmdLine	cmdLine(argc, argv, "bC:cDd:f:Hh:i:l:M:mqo:r:st:T:vV:w:");
	while ((c = cmdLine.next(&argp)) != EOF) {
		switch(c) {
		case 'b':
			benchmark++;
			break;

		case 'c':
			continueOnErrors++;
			break;

		case 'C':
			cmpDir = argp;
			break;

		case 'd':
			postData = argp;
			postLen = strlen(postData);
			break;

		case 'D':
			mprSetDebugMode(1);
			break;

		case 'f':
			fileList = argp;
			break;

		case 'h':
			host = argp;
			break;

		case 'H':
			outputHeader++;
			break;

		case 'i':
			iterations = atoi(argp);
			break;

		case 'l':
			logSpec = argp;
			break;

		case 'm':
			mprRequestMemStats(1);
			break;

		case 'M':
			method = argp;
			break;

		case 'o':
			timeout = atoi(argp);
			break;

		case 'q':
			quietMode++;
			break;

		case 'r':
			retries = atoi(argp);
			break;

		case 's':
			singleStep++;
			break;

		case 't':
			loadThreads = atoi(argp);
			break;

		case 'T':
			poolThreads = atoi(argp);
			break;

		case 'v':
			verbose++;
			trace++;
			break;

		case 'V':
			httpVersion = atoi(argp);
			break;

		case 'w':
			writeDir = argp;
			break;

		default:
			errflg++;
			break;
		}
	}
	if (writeDir && (loadThreads > 1)) {
		errflg++;
	}

	if (errflg) {
		mprFprintf(MPR_STDERR, 
			"usage: %s [-bcHMmqsTv] [-C cmpDir] [-d postData] [-f fileList]\n"
			"	[-i iterations] [-l logSpec] [-M method] [-o timeout]\n"
			"	[-h host] [-r retries] [-t threads] [-T poolThreads]\n"
			"	[-V httpVersion] [-w writeDir] [urls...]\n", programName);
		exit(2);
	}
	saveArgc = argc - cmdLine.firstArg();
	saveArgv = &argv[cmdLine.firstArg()];

	mpr = new Mpr(programName);

#if BLD_FEATURE_LOG
	tMod = new MprLogModule("httpClient");
	logger = new MprLogToFile();
	mpr->addListener(logger);
	if (mpr->setLogSpec(logSpec) < 0) {
		mprFprintf(MPR_STDERR, "Can't open log file %s\n", logSpec);
		exit(2);
	}
#endif

	//
	//	Alternatively, set the configuration manually
	//
	mpr->setAppTitle("Embedthis HTTP Client");
#if BLD_FEATURE_MULTITHREAD
	mpr->setMaxPoolThreads(poolThreads);
#endif

	//
	//	Start the Timer, Socket and Pool services
	//
	if (mpr->start(MPR_SERVICE_THREAD) < 0) {
		mprError(MPR_L, MPR_USER, "Can't start MPR for %s", mpr->getAppTitle());
		delete mpr;
		exit(2);
	}

	//
	//	Create extra test threads to run the tests as required. We use
	//	the main thread also (so start with j==1)
	//
	start = mprGetTime(0);
#if BLD_FEATURE_MULTITHREAD
	activeLoadThreads = loadThreads;
	for (int j = 1; j < loadThreads; j++) {
		char name[64];
		mprSprintf(name, sizeof(name), "t.%d", j - 1);
		threadp = new MprThread(doTests, MPR_NORMAL_PRIORITY, (void*) j, name); 
		threadp->start();
	}
#endif

	doTests(0, 0);

	//
	//	Wait for all the threads to complete (simple but effective). Keep 
	//	servicing events as we wind down.
	//
	while (activeLoadThreads > 1) {
		mprSleep(100);
	}

	if (benchmark && success) {
		elapsed = (mprGetTime(0) - start);
		if (fetchCount == 0) {
			elapsed = 0;
			fetchCount = 1;
		}
		mprPrintf("\tThreads %d, Pool Threads %d   \t%13.2f\t%12.2f\t%6d\n", 
			loadThreads, poolThreads, elapsed * 1000.0 / fetchCount, 
			elapsed / 1000.0, fetchCount);

		mprPrintf("\nTime elapsed:        %13.4f sec\n", elapsed / 1000.0);
		mprPrintf("Time per request:    %13.4f sec\n", elapsed / 1000.0 
			/ fetchCount);
		mprPrintf("Requests per second: %13.4f\n", fetchCount * 1.0 / 
			(elapsed / 1000.0));
	}
	if (! quietMode) {
		mprPrintf("\n");
	}

	mpr->stop(0);

#if BLD_FEATURE_MULTITHREAD
	delete mutex;
#endif
#if BLD_FEATURE_LOG
	delete tMod;
#endif

	delete mpr;
#if BLD_FEATURE_LOG
	delete logger;
#endif
	mprMemClose();
	return (success) ? 0 : 255;
}
Пример #28
0
/*
    Convert this Manager to a Deaemon
 */
static int makeDaemon()
{
    struct sigaction    act, old;
    int                 pid, status;

    /*
        Ignore child death signals
     */
    memset(&act, 0, sizeof(act));
    act.sa_sigaction = (void (*)(int, siginfo_t*, void*)) SIG_DFL;
    sigemptyset(&act.sa_mask);
    act.sa_flags = SA_NOCLDSTOP | SA_RESTART | SA_SIGINFO;

    if (sigaction(SIGCHLD, &act, &old) < 0) {
        mprError("Can't initialize signals");
        return MPR_ERR_BAD_STATE;
    }

    /*
        Fork twice to get a free child with no parent
     */
    if ((pid = fork()) < 0) {
        mprError("Fork failed for background operation");
        return MPR_ERR;

    } else if (pid == 0) {
        if ((pid = fork()) < 0) {
            mprError("Second fork failed");
            exit(127);

        } else if (pid > 0) {
            /* Parent of second child -- must exit */
            exit(0);
        }

        /*
            This is the real child that will continue as a daemon
         */
        setsid();
        if (sigaction(SIGCHLD, &old, 0) < 0) {
            mprError("Can't restore signals");
            return MPR_ERR_BAD_STATE;
        }
        mprLog(2, "Switching to background operation");
        return 0;
    }

    /*
        Original process waits for first child here. Must get child death notification with a successful exit status
     */
    while (waitpid(pid, &status, 0) != pid) {
        if (errno == EINTR) {
            mprSleep(100);
            continue;
        }
        mprError("Can't wait for daemon parent.");
        exit(0);
    }
    if (WEXITSTATUS(status) != 0) {
        mprError("Daemon parent had bad exit status.");
        exit(0);
    }
    if (sigaction(SIGCHLD, &old, 0) < 0) {
        mprError("Can't restore signals");
        return MPR_ERR_BAD_STATE;
    }
    exit(0);
}
Пример #29
0
static void runService()
{
    MprTime     mark;
    char        **av, *env[3], **argv;
    int         err, i, status, ac, next;

    app->servicePid = 0;
    atexit(cleanup);

    mprLog(1, "%s: Watching over %s", app->appName, app->serviceProgram);

    if (access(app->serviceProgram, X_OK) < 0) {
        mprError("start: can't access %s, errno %d", app->serviceProgram, mprGetOsError());
        return;
    }
    if (writePid(getpid()) < 0) {
        return;
    }
    mark = mprGetTime();

    while (!mprIsStopping()) {
        if (mprGetElapsedTime(mark) > (3600 * 1000)) {
            mark = mprGetTime();
            app->restartCount = 0;
            app->restartWarned = 0;
        }
        if (app->servicePid == 0) {
            if (app->restartCount >= app->retries) {
                if (! app->restartWarned) {
                    mprError("Too many restarts for %s, %d in ths last hour", app->serviceProgram, app->restartCount);
                    mprError("Suspending restarts for one hour");
                    app->restartWarned++;
                }
                mprSleep(60 * 1000);
                continue;
            }

            /*
                Create the child
             */
            app->servicePid = vfork();
            if (app->servicePid < 0) {
                mprError("Can't fork new process to run %s", app->serviceProgram);
                continue;

            } else if (app->servicePid == 0) {
                /*
                    Child
                 */
                umask(022);
                setsid();

                mprLog(1, "%s: Change dir to %s", app->appName, app->serviceHome);
                if (chdir(app->serviceHome) < 0) {}

                for (i = 3; i < 128; i++) {
                    close(i);
                }
                if (app->serviceArgs && *app->serviceArgs) {
                    ac = mprMakeArgv(app->serviceArgs, &av, 0);
                } else {
                    ac = 0;
                }
                argv = mprAlloc(sizeof(char*) * (6 + ac));
                env[0] = sjoin("LD_LIBRARY_PATH=", app->serviceHome, NULL);
                env[1] = sjoin("PATH=", getenv("PATH"), NULL);
                env[2] = 0;

                next = 0;
                argv[next++] = app->serviceProgram;
                if (app->logSpec) {
                    argv[next++] = "--log";
                    argv[next++] = (char*) app->logSpec;
                }
                for (i = 0; i < ac; i++) {
                    argv[next++] = av[i];
                }
                argv[next++] = 0;

                mprLog(1, "%s: Running %s", app->appName, app->serviceProgram);
                for (i = 1; argv[i]; i++) {
                    mprLog(1, "%s: argv[%d] = %s", app->appName, i, argv[i]);
                }
                execve(app->serviceProgram, argv, (char**) &env);

                /* Should not get here */
                err = errno;
                mprError("%s: Can't exec %s, err %d, cwd %s", app->appName, app->serviceProgram, err, app->serviceHome);
                exit(MPR_ERR_CANT_INITIALIZE);
            }

            /*
                Parent
             */
            mprLog(1, "%s: create child %s at pid %d", app->appName, app->serviceProgram, app->servicePid);
            app->restartCount++;

            waitpid(app->servicePid, &status, 0);
            mprLog(1, "%s: %s has exited with status %d", app->appName, app->serviceProgram, WEXITSTATUS(status));
            if (!mprIsStopping()) {
                mprLog(1, "%s: Restarting %s (%d/%d)...", 
                    app->appName, app->serviceProgram, app->restartCount, app->retries);
            }
            app->servicePid = 0;
        }
    }
}
Пример #30
0
int main(int argc, char *argv[], char *envp[])
#endif
{
    char    *cp, *method;
    int     i, j, err;

    err = 0;
    outputArgs = outputQuery = outputEnv = outputPost = 0;
    outputBytes = outputHeaderLines = responseStatus = 0;
    outputLocation = 0;
    nonParsedHeader = 0;
    responseMsg = 0;
    hasError = 0;
    timeout = 0;
    queryBuf = 0;
    queryLen = 0;
    numQueryKeys = numPostKeys = 0;

    originalArgc = argc;
    originalArgv = argv;

    mpr = mprCreate(argc, argv, NULL);

#if _WIN32 && !WINCE
    _setmode(0, O_BINARY);
    _setmode(1, O_BINARY);
    _setmode(2, O_BINARY);
#endif

    if (strncmp(mprGetPathBase(mpr, argv[0]), "nph-", 4) == 0) {
        nonParsedHeader++;
    }
    if (getArgv(mpr, &argc, &argv, originalArgc, originalArgv) < 0) {
        error(mpr, "Can't read CGI input");
    }

    for (i = 1; i < argc; i++) {
        if (argv[i][0] != '-') {
            continue;
        }
        for (cp = &argv[i][1]; *cp; cp++) {
            switch (*cp) {
            case 'a':
                outputArgs++;
                break;

            case 'b':
                if (++i >= argc) {
                    err = __LINE__;
                } else {
                    outputBytes = atoi(argv[i]);
                }
                break;

            case 'e':
                outputEnv++;
                break;

            case 'h':
                if (++i >= argc) {
                    err = __LINE__;
                } else {
                    outputHeaderLines = atoi(argv[i]);
                    nonParsedHeader++;
                }
                break;

            case 'l':
                if (++i >= argc) {
                    err = __LINE__;
                } else {
                    outputLocation = argv[i];
                    if (responseStatus == 0) {
                        responseStatus = 302;
                    }
                }
                break;

            case 'n':
                nonParsedHeader++;
                break;

            case 'p':
                outputPost++;
                break;

            case 'q':
                outputQuery++;
                break;

            case 's':
                if (++i >= argc) {
                    err = __LINE__;
                } else {
                    responseStatus = atoi(argv[i]);
                }
                break;

            case 't':
                if (++i >= argc) {
                    err = __LINE__;
                } else {
                    timeout = atoi(argv[i]);
                }
                break;

            default:
                err = __LINE__;
                break;
            }
        }
    }
    if (err) {
        mprError(mpr, "usage: cgiProgram -aenp [-b bytes] [-h lines]\n"
            "\t[-l location] [-s status] [-t timeout]\n"
            "\tor set the HTTP_SWITCHES environment variable\n");
        mprError(mpr, "Error at cgiProgram:%d\n", __LINE__);
        exit(255);
    }

    method = getenv("REQUEST_METHOD") ;
    if (method == 0) {
        method = "GET";
    } else {
        if (strcmp(method, "POST") == 0) {
            postBuf = mprCreateBuf(mpr, -1, -1);
            if (getPostData(mpr, postBuf) < 0) {
                error(mpr, "Can't read CGI input");
            }
            if (strcmp(safeGetenv("CONTENT_TYPE"), "application/x-www-form-urlencoded") == 0) {
                numPostKeys = getVars(mpr, &postKeys, mprGetBufStart(postBuf), mprGetBufLength(postBuf));
            }
        }
    }

    if (hasError) {
        if (! nonParsedHeader) {
            mprPrintf(mpr, "HTTP/1.0 %d %s\r\n\r\n", responseStatus, responseMsg);
            mprPrintf(mpr, "<HTML><BODY><p>Error: %d -- %s</p></BODY></HTML>\r\n", responseStatus, responseMsg);
        }
        exit(2);
    }

    if (nonParsedHeader) {
        if (responseStatus == 0) {
            mprPrintf(mpr, "HTTP/1.0 200 OK\r\n");
        } else {
            mprPrintf(mpr, "HTTP/1.0 %d %s\r\n", responseStatus, responseMsg ? responseMsg: "");
        }
        mprPrintf(mpr, "Connection: close\r\n");
        mprPrintf(mpr, "X-CGI-CustomHeader: Any value at all\r\n");
    }

    mprPrintf(mpr, "Content-type: %s\r\n", "text/html");

    if (outputHeaderLines) {
        j = 0;
        for (i = 0; i < outputHeaderLines; i++) {
            mprPrintf(mpr, "X-CGI-%d: A loooooooooooooooooooooooong string\r\n", i);
        }
    }

    if (outputLocation) {
        mprPrintf(mpr, "Location: %s\r\n", outputLocation);
    }
    if (responseStatus) {
        mprPrintf(mpr, "Status: %d\r\n", responseStatus);
    }
    mprPrintf(mpr, "\r\n");

    if ((outputBytes + outputArgs + outputEnv + outputQuery + outputPost + outputLocation + responseStatus) == 0) {
        outputArgs++;
        outputEnv++;
        outputQuery++;
        outputPost++;
    }

    if (outputBytes) {
        j = 0;
        for (i = 0; i < outputBytes; i++) {
            putchar('0' + j);
            j++;
            if (j > 9) {
                if (++outputBytes > 0) {
                    putchar('\r');
                }
                if (++outputBytes > 0) {
                    putchar('\n');
                }
                j = 0;
            }
        }

    } /* else */ {
        mprPrintf(mpr, "<HTML><TITLE>cgiProgram: Output</TITLE><BODY>\r\n");
        if (outputArgs) {
#if _WIN32
            mprPrintf(mpr, "<P>CommandLine: %s</P>\r\n", GetCommandLine());
#endif
            mprPrintf(mpr, "<H2>Args</H2>\r\n");
            for (i = 0; i < argc; i++) {
                mprPrintf(mpr, "<P>ARG[%d]=%s</P>\r\n", i, argv[i]);
            }
        }
#if !VXWORKS && !WINCE
        if (outputEnv) {
            printEnv(envp);
        }
#endif
        if (outputQuery) {
            printQuery();
        }
        if (outputPost) {
            printPost(postBuf);
        }
        if (timeout) {
            mprSleep(mpr, timeout * MPR_TICKS_PER_SEC);
        }
        mprPrintf(mpr, "</BODY></HTML>\r\n");
    }
#if VXWORKS
/*
 *  VxWorks pipes need an explicit eof string
 */
    
    write(1, MPR_CMD_VXWORKS_EOF, MPR_CMD_VXWORKS_EOF_LEN);
    write(2, MPR_CMD_VXWORKS_EOF, MPR_CMD_VXWORKS_EOF_LEN);

    /*
     *  Must not call exit(0) in Vxworks as that will exit the task before the CGI handler can cleanup. Must use return 0.
     */
#endif
    return 0;
}