| opends/lib/opends_service.exe | patch | view | raw | blame | history | |
| opends/lib/winlauncher.exe | patch | view | raw | blame | history | |
| opends/resource/bin/start-ds.bat | ●●●●● patch | view | raw | blame | history | |
| opends/resource/bin/stop-ds.bat | ●●●●● patch | view | raw | blame | history | |
| opends/src/build-tools/windows/common.c | ●●●●● patch | view | raw | blame | history | |
| opends/src/build-tools/windows/common.h | ●●●●● patch | view | raw | blame | history | |
| opends/src/build-tools/windows/service.c | ●●●●● patch | view | raw | blame | history | |
| opends/src/build-tools/windows/service.h | ●●●●● patch | view | raw | blame | history | |
| opends/src/build-tools/windows/winlauncher.c | ●●●●● patch | view | raw | blame | history | |
| opends/src/build-tools/windows/winlauncher.h | ●●●●● patch | view | raw | blame | history |
opends/lib/opends_service.exeBinary files differ
opends/lib/winlauncher.exeBinary files differ
opends/resource/bin/start-ds.bat
@@ -30,6 +30,11 @@ set DIR_HOME=%~dP0.. set INSTANCE_ROOT=%DIR_HOME% set LOG=%INSTANCE_ROOT%\logs\native-windows.out set SCRIPT=start-ds.bat echo %SCRIPT%: invoked >> %LOG% :checkJavaBin if "%JAVA_BIN%" == "" goto noJavaBin goto setClassPath @@ -47,11 +52,13 @@ goto setClassPath :noSetJavaHome echo %SCRIPT%: JAVA_HOME environment variable is not set. >> %LOG% echo Error: JAVA_HOME environment variable is not set. echo Please set it to a valid Java 5 (or later) installation. goto end :noValidJavaHome echo %SCRIPT%: The detected Java version could notf be used. JAVA_HOME=[%JAVA_HOME%] >> %LOG% echo ERROR: The detected Java version could not be used. Please set echo JAVA_HOME to to a valid Java 5 (or later) installation. goto end @@ -59,8 +66,12 @@ :setClassPath FOR %%x in ("%DIR_HOME%\lib\*.jar") DO call "%DIR_HOME%\lib\setcp.bat" %%x echo %SCRIPT%: CLASSPATH=%CLASSPATH% >> %LOG% set PATH=%SystemRoot% echo %SCRIPT%: PATH=%PATH% >> %LOG% set SCRIPT_NAME_ARG=-Dorg.opends.server.scriptName=start-ds rem Test that the provided JDK is 1.5 compatible. @@ -77,9 +88,11 @@ goto end :serverAlreadyStarted echo %SCRIPT%: Server already started >> %LOG% goto end :runNoDetach echo %SCRIPT%: Run no detach >> %LOG% if not exist "%DIR_HOME%\logs\server.out" echo. > "%DIR_HOME%\logs\server.out" if not exist "%DIR_HOME%\logs\server.starting" echo. > "%DIR_HOME%\logs\server.starting" "%JAVA_BIN%" %JAVA_ARGS% org.opends.server.core.DirectoryServer --configClass org.opends.server.extensions.ConfigFileHandler --configFile "%DIR_HOME%\config\config.ldif" %* @@ -87,28 +100,35 @@ :runDetach echo %SCRIPT%: Run detach >> %LOG% if not exist "%DIR_HOME%\logs\server.out" echo. > "%DIR_HOME%\logs\server.out" if not exist "%DIR_HOME%\logs\server.starting" echo. > "%DIR_HOME%\logs\server.starting" "%DIR_HOME%\lib\winlauncher.exe" start "%DIR_HOME%" "%JAVA_BIN%" %JAVA_ARGS% org.opends.server.core.DirectoryServer --configClass org.opends.server.extensions.ConfigFileHandler --configFile "%DIR_HOME%\config\config.ldif" %* echo %SCRIPT%: Waiting for "%DIR_HOME%\logs\server.out" to be deleted >> %LOG% "%JAVA_BIN%" -Xms8M -Xmx8M org.opends.server.tools.WaitForFileDelete --targetFile "%DIR_HOME%\logs\server.starting" --logFile "%DIR_HOME%\logs\server.out" goto end :runDetachCalledByWinService rem We write the output of the start command to the winwervice.out file. echo %SCRIPT%: Run detach called by windows service >> %LOG% if not exist "%DIR_HOME%\logs\server.out" echo. > "%DIR_HOME%\logs\server.out" if not exist "%DIR_HOME%\logs\server.starting" echo. > "%DIR_HOME%\logs\server.starting" echo. > "%DIR_HOME%\logs\server.startingservice" echo. > "%DIR_HOME%\logs\winservice.out" "%DIR_HOME%\lib\winlauncher.exe" start "%DIR_HOME%" "%JAVA_BIN%" %JAVA_ARGS% org.opends.server.core.DirectoryServer --configClass org.opends.server.extensions.ConfigFileHandler --configFile "%DIR_HOME%\config\config.ldif" %* echo %SCRIPT%: Waiting for "%DIR_HOME%\logs\server.out" to be deleted >> %LOG% "%JAVA_BIN%" -Xms8M -Xmx8M org.opends.server.tools.WaitForFileDelete --targetFile "%DIR_HOME%\logs\server.starting" --logFile "%DIR_HOME%\logs\server.out" --outputFile "%DIR_HOME%\logs\winservice.out" erase "%DIR_HOME%\logs\server.startingservice" goto end :runAsService echo %SCRIPT%: Run as service >> %LOG% "%JAVA_BIN%" -Xms8M -Xmx8M org.opends.server.tools.StartWindowsService echo %SCRIPT%: Waiting for "%DIR_HOME%\logs\server.startingservice" to be deleted >> %LOG% "%JAVA_BIN%" -Xms8M -Xmx8M org.opends.server.tools.WaitForFileDelete --targetFile "%DIR_HOME%\logs\server.startingservice" rem Type the contents the winwervice.out file and delete it. if exist "%DIR_HOME%\logs\winservice.out" type "%DIR_HOME%\logs\winservice.out" if exist "%DIR_HOME%\logs\winservice.out" erase "%DIR_HOME%\logs\winservice.out" :end echo %SCRIPT%: finished >> %LOG% opends/resource/bin/stop-ds.bat
@@ -33,6 +33,15 @@ set SCRIPT_NAME_ARG="-Dorg.opends.server.scriptName=stop-ds" set DIR_HOME=%~dP0.. set INSTANCE_ROOT=%DIR_HOME% set LOG=%INSTANCE_ROOT%\logs\native-windows.out set SCRIPT=stop-ds.bat rem This is the template to use for logging. Make sure to use >> rem echo %SCRIPT%: your-message-here >> %LOG% echo %SCRIPT%: invoked >> %LOG% :checkJavaBin if "%JAVA_BIN%" == "" goto noJavaBin goto setClassPath @@ -52,9 +61,11 @@ :noSetJavaHome echo Error: JAVA_HOME environment variable is not set. echo Please set it to a valid Java 5 (or later) installation. echo %SCRIPT%: JAVA_HOME environment variable is not set. >> %LOG% goto end :noValidJavaHome echo %SCRIPT%: The detected Java version could not be used. JAVA_HOME=[%JAVA_HOME%] >> %LOG% echo ERROR: The detected Java version could not be used. Please set echo JAVA_HOME to to a valid Java 5 (or later) installation. goto end @@ -62,6 +73,8 @@ :setClassPath FOR %%x in ("%DIR_HOME%\lib\*.jar") DO call "%DIR_HOME%\lib\setcp.bat" %%x echo %SCRIPT%: CLASSPATH=%CLASSPATH% >> %LOG% rem Test that the provided JDK is 1.5 compatible. "%JAVA_BIN%" org.opends.server.tools.InstallDS -t > NUL 2>&1 if not %errorlevel% == 0 goto noValidJavaHome @@ -79,33 +92,41 @@ goto end :serverAlreadyStopped echo %SCRIPT%: server already stopped >> %LOG% if exist "%DIR_HOME%\logs\server.pid" erase "%DIR_HOME%\logs\server.pid" goto end :startUsingSystemCall echo %SCRIPT%: start using system call >> %LOG% "%DIR_HOME%\bat\start-ds.bat" goto end :stopUsingSystemCall echo %SCRIPT%: stop using system call >> %LOG% "%DIR_HOME%\lib\winlauncher.exe" stop "%DIR_HOME%" goto end :restartUsingSystemCall echo %SCRIPT%: restart using system call >> %LOG% "%DIR_HOME%\lib\winlauncher.exe" stop "%DIR_HOME%" if not %errorlevel% == 0 goto end goto startUsingSystemCall :stopUsingProtocol echo %SCRIPT%: stop using protocol >> %LOG% call "%DIR_HOME%\lib\_client-script.bat" %* goto end :stopAsWindowsService echo %SCRIPT%: stop as windows service >> %LOG% "%JAVA_BIN%" -Xms8M -Xmx8M org.opends.server.tools.StopWindowsService goto end :restartAsWindowsService echo %SCRIPT%: restart as windows service, stopping >> %LOG% "%JAVA_BIN%" -Xms8M -Xmx8M org.opends.server.tools.StopWindowsService if not %errorlevel% == 0 goto end echo %SCRIPT%: restart as windows service, starting >> %LOG% "%JAVA_BIN%" -Xms8M -Xmx8M org.opends.server.tools.StartWindowsService "%JAVA_BIN%" -Xms8M -Xmx8M org.opends.server.tools.WaitForFileDelete --targetFile "%DIR_HOME%\logs\server.startingservice" rem Type the contents the winwervice.out file and delete it. @@ -115,3 +136,4 @@ :end echo %SCRIPT%: finished >> %LOG% opends/src/build-tools/windows/common.c
@@ -26,6 +26,19 @@ */ #include "common.h" #include <errno.h> #include <fcntl.h> #include <io.h> #include <stdio.h> #include <sys/locking.h> #include <time.h> BOOL DEBUG = TRUE; char * DEBUG_LOG_NAME = "native-windows.out"; DWORD MAX_DEBUG_LOG_SIZE = 500 * 1000; char * getDebugLogFileName(); void debugInner(BOOL isError, const char *msg, va_list ap); void deleteIfLargerThan(char * fileName, DWORD maxSize); // ---------------------------------------------------- // Function used to create a process with the given command. @@ -40,6 +53,8 @@ STARTUPINFO startInfo; // info to pass to the new process DWORD processFlag; // background process flag debug("Attempting to child process '%s' background=%d.", command, background); // reset process info first ZeroMemory(procInfo, sizeof(PROCESS_INFORMATION)); @@ -51,18 +66,27 @@ // Create the child process processFlag = background == TRUE ? DETACHED_PROCESS : 0; createOk = CreateProcess( NULL, // application name command, // command line NULL, // process security attributes NULL, // primary thread security attributes TRUE, // handles are inherited processFlag, // creation flags NULL, // use parent's environment NULL, // use parent's current directory &startInfo, // STARTUPINFO pointer procInfo // receives PROCESS_INFORMATION NULL, // application name command, // command line NULL, // process security attributes NULL, // primary thread security attributes TRUE, // handles are inherited processFlag, // creation flags NULL, // use parent's environment NULL, // use parent's current directory &startInfo, // STARTUPINFO pointer procInfo // receives PROCESS_INFORMATION ); if (createOk) { debug("Successfully created child process '%s'.", command); } else { debugError("Failed to create child process '%s'. Last error = %d.", command, GetLastError()); } return createOk; } // createChildProcess @@ -73,7 +97,7 @@ // ---------------------------------------------------- int spawn(const char* command, BOOL background) { DWORD childPid; // child's pid DWORD childPid = -1; // child's pid PROCESS_INFORMATION procInfo; // info on the new process BOOL createOk; @@ -86,11 +110,167 @@ if (childPid != -1) { debug("The PID of the spawned process is %d.", childPid); return childPid; } else { debugError("Could not get the PID of the spawned process."); return -1; } } // spawn // --------------------------------------------------- // Debug utility. // --------------------------------------------------- void debug(const char *msg, ...) { va_list ap; va_start (ap, msg); debugInner(FALSE, msg, ap); va_end (ap); } void debugError(const char *msg, ...) { va_list ap; va_start (ap, msg); debugInner(TRUE, msg, ap); va_end (ap); } void debugInner(BOOL isError, const char *msg, va_list ap) { static DWORD currentProcessPid = 0; static BOOL noMessageLogged = TRUE; // The file containing the log. char * logFile; FILE *fp; time_t rawtime; struct tm * timeinfo; char formattedTime[100]; if (noMessageLogged) { currentProcessPid = GetCurrentProcessId(); noMessageLogged = FALSE; debug("--------------- FIRST LOG MESSAGE FROM '%s' ---------------", _pgmptr); } // Time-stamp time(&rawtime); timeinfo = localtime(&rawtime); strftime(formattedTime, 100, "%Y/%m/%d %H:%M:%S", timeinfo); logFile = getDebugLogFileName(); deleteIfLargerThan(logFile, MAX_DEBUG_LOG_SIZE); if ((fp = fopen(logFile, "a")) != NULL) { fprintf(fp, "%s: (pid=%d) ", formattedTime, currentProcessPid); if (isError) { fprintf(fp, "ERROR: "); // It would be nice to echo to stderr, but that doesn't appear to work. } vfprintf(fp, msg, ap); fprintf(fp, "\n"); fclose(fp); } else { fprintf(stdout, "Could not create log file.\n"); } } // --------------------------------------------------------------- // Get the fully-qualified debug log file name. The logic in this // method assumes that the executable of this process is in a // direct subdirectory of the instance root. // --------------------------------------------------------------- char * getDebugLogFileName() { static char * logFile = NULL; char path [MAX_PATH]; char execName [MAX_PATH]; char * lastSlash; if (logFile != NULL) { return logFile; } // Get the name of the executable. GetModuleFileName ( NULL, execName, MAX_PATH ); // Cut everything after the last slash, twice. This will take us back to the instance root. // This logic assumes that we are in a directory above the instance root. lastSlash = strrchr(execName, '\\'); lastSlash[0] = '\0'; lastSlash = strrchr(execName, '\\'); lastSlash[0] = '\0'; sprintf(path, "%s\\logs\\%s", execName, DEBUG_LOG_NAME); logFile = _strdup(path); return logFile; } // --------------------------------------------------------------- // Function called to know if the --debug option was passed // when calling this executable or not. The DEBUG variable is // updated accordingly. // --------------------------------------------------------------- void updateDebugFlag(char* argv[], int argc) { int i; DEBUG = FALSE; for (i=1; (i<argc) && !DEBUG; i++) { if (strcmp(argv[i], "--debug") == 0) { DEBUG = TRUE; } } } // --------------------------------------------------------------- // Deletes a file if it's larger than the given maximum size. // --------------------------------------------------------------- void deleteIfLargerThan(char * fileName, DWORD maxSize) { DWORD fileSize = 0; HANDLE fileHandle = CreateFile( fileName, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL ); if (fileHandle == INVALID_HANDLE_VALUE) { return; } fileSize = GetFileSize(fileHandle, NULL); CloseHandle(fileHandle); if (fileSize > maxSize) { DeleteFile(fileName); } } opends/src/build-tools/windows/common.h
@@ -28,8 +28,14 @@ // Just some functions and constants to be used by winlauncher.c // and service.c // This stops warnings about deprecation of stdio functions #define _CRT_SECURE_NO_DEPRECATE 1 #include <Windows.h> int spawn(const char* command, BOOL background); BOOL createChildProcess(char* command, BOOL background, PROCESS_INFORMATION* procInfo); void debug(const char *msg, ...); void debugError(const char *msg, ...); void updateDebugFlag(char* argv[], int argc); opends/src/build-tools/windows/service.c
@@ -33,8 +33,6 @@ char *_instanceDir = NULL; HANDLE _eventLog = NULL; char * _logFile = NULL; BOOL DEBUG = FALSE; // ---------------------------------------------------- // Register a service handler to the service control dispatcher. @@ -58,6 +56,8 @@ { ServiceReturnCode returnValue; debug("Registering the service handler for '%s'", serviceName); // register the service to the service control dispatcher (SCM) *serviceStatusHandle = RegisterServiceCtrlHandler ( serviceName, (LPHANDLER_FUNCTION) serviceHandler @@ -70,89 +70,13 @@ { returnValue = SERVICE_RETURN_OK; } debug("registerServiceHandler returning '%d'", returnValue); return returnValue; } // registerServiceHandler // --------------------------------------------------- // Debug utility. // If the _eventLog is NULL and the DEBUG variable is TRUE write the message // in a log file. // --------------------------------------------------- void debug(char* msg) { if (DEBUG == TRUE) { /* if (_eventLog != NULL) { const char* args[1]; args[0] = msg; // report the event ReportEvent( _eventLog, // event log handle EVENTLOG_INFORMATION_TYPE, // info, warning, error WIN_FACILITY_NAME_OPENDS, // unique category for OPENDS WIN_EVENT_ID_DEBUG, NULL, // no user security identifier 1, // number of args 0, // raw data size (const char**)args, // args NULL // no war data ); } */ // Log to the file FILE *fp; if (_logFile == NULL) { char path [MAX_PATH]; if (_instanceDir != NULL) { int length = strlen(_instanceDir); if ((length > 0) && (_instanceDir[length - 1] == '\\')) { sprintf(path, "%slogs\\windows-service.out", _instanceDir); _logFile = strdup(path); } else { sprintf(path, "%s\\logs\\windows-service.out", _instanceDir); _logFile = strdup(path); } } else { char execName [MAX_PATH]; char instanceDir [MAX_PATH]; int length; GetModuleFileName ( NULL, execName, MAX_PATH ); length = strlen(execName) - strlen("lib\\opends_service.exe"); if (length > 0) { strncpy(instanceDir, execName, length); instanceDir[length] = '\0'; sprintf(path, "%slogs\\windows-service.out", instanceDir); _logFile = strdup(path); } } } if ((_logFile != NULL) && ((fp = fopen(_logFile, "a")) != NULL)) { fprintf(fp, "%s\n", msg); fclose(fp); } else { fprintf(stdout, "Could not create log file.\n"); } } } // --------------------------------------------------- // Reports a log event of a given type, id and arguments @@ -223,11 +147,12 @@ ); if (scm == NULL) { debug("scm is NULL."); debugError("Failed to open the Service Control Manager. Last error = %d", GetLastError()); returnValue = SERVICE_RETURN_ERROR; } else { debug("Successfully opened the Service Control Manager."); returnValue = SERVICE_RETURN_OK; } return returnValue; @@ -262,6 +187,9 @@ // here because we already required it to figure out to get the service // name based on the command to run associated with it. char execName [MAX_PATH]; debug("Creating registry key for service '%s'.", serviceName); GetModuleFileName ( NULL, execName, @@ -280,6 +208,7 @@ ); if (result == ERROR_SUCCESS) { debug("The registry key for service '%s' already exists.", serviceName); alreadyRegistered = TRUE; success = FALSE; } @@ -300,7 +229,7 @@ ); if (result != ERROR_SUCCESS) { debug("RegCreateKeyEx failed."); debugError("RegCreateKeyEx failed, result=%d.", result); success = FALSE; } } @@ -318,6 +247,7 @@ ); if (result != ERROR_SUCCESS) { debugError("RegSetValueEx('EventMessageFile') failed, result=%d.", result); success = FALSE; } } @@ -341,6 +271,7 @@ ); if (result != ERROR_SUCCESS) { debugError("RegSetValueEx('TypesSupported') failed, result=%d.", result); success = FALSE; } } @@ -359,6 +290,7 @@ ); if (result != ERROR_SUCCESS) { debugError("RegSetValueEx('CategoryMessageFile') failed, result=%d.", result); success = FALSE; } } @@ -376,6 +308,7 @@ ); if (result != ERROR_SUCCESS) { debugError("RegSetValueEx('CategoryCount') failed, result=%d.", result); success = FALSE; } } @@ -392,7 +325,7 @@ } else { debug("Could not create a registry key."); debugError("Could not create a registry key."); return FALSE; } } // createRegistryKey @@ -406,7 +339,7 @@ // --------------------------------------------------- BOOLEAN removeRegistryKey(char* serviceName) { BOOL returnValue; BOOL returnValue = FALSE; // Create the event source subkey (or open it if it already exists) char subkey [MAX_REGISTRY_KEY]; @@ -415,6 +348,8 @@ HKEY hkey = NULL; debug("Removing registry key for service '%s'.", serviceName); // Check whether the Registry Key is already created, // If so don't create a new one. sprintf (subkey, EVENT_LOG_KEY, serviceName); @@ -427,6 +362,7 @@ ); if (result != ERROR_SUCCESS) { debug("The registry key for service '%s' does not exist, so we do not need to remove it.", serviceName); // Assume that the registry key does not exist. returnValue = TRUE; } @@ -437,6 +373,10 @@ { returnValue = TRUE; } else { debugError("RegDeleteKey('%s') failed, result=%d.", subkey, result); } } return returnValue; @@ -453,6 +393,8 @@ // subkey under Eventlog registry key char subkey [MAX_SERVICE_NAME]; debug("Registering the Event Log for service '%s'.", serviceName); sprintf (subkey, serviceName); eventLog = RegisterEventSource( @@ -471,6 +413,7 @@ { if (_eventLog != NULL) { debug("Deregistering the Event Log."); DeregisterEventSource(_eventLog); } } @@ -485,21 +428,26 @@ ServiceReturnCode returnValue; char* relativePath = "\\locks\\server.lock"; char lockFile[MAX_PATH]; debug("Determining if the server is running."); if (strlen(relativePath)+strlen(_instanceDir)+1 < MAX_PATH) { int fd; sprintf(lockFile, "%s%s", _instanceDir, relativePath); debug("When determining whether the server is running, the lock file name is '%s'.", lockFile); fd = _open(lockFile, _O_RDWR); if (fd != -1) { debug("Able to open the lock file '%s'.", lockFile); returnValue = SERVICE_RETURN_OK; // Test if there is a lock /* Lock some bytes and read them. Then unlock. */ if(_locking(fd, LK_NBLCK, 1) != -1) { debug("Able to lock '%s', so the server is not running.", lockFile); *running = FALSE; _locking(fd, LK_UNLCK, 1); } @@ -507,20 +455,21 @@ { if (errno == EACCES) { debug("Unable to lock '%s', so the server is running.", lockFile); *running = TRUE; } else { *running = FALSE; returnValue = SERVICE_RETURN_ERROR; debug("Unexpected error locking"); debugError("Unexpected error locking: %d", errno); } } _close(fd); } else { debug("Could not open lock file."); debug("Could not open lock file '%s', which means the server is not running.", lockFile); *running = FALSE; returnValue = SERVICE_RETURN_ERROR; } @@ -531,6 +480,7 @@ *running = FALSE; returnValue = SERVICE_RETURN_ERROR; } return returnValue; } // isServerRunning @@ -545,35 +495,40 @@ // init out params char* relativePath = "\\bat\\start-ds.bat"; char command[COMMAND_SIZE]; debug("doStartApplication called."); if (strlen(relativePath)+strlen(_instanceDir)+1 < COMMAND_SIZE) { sprintf(command, "\"%s%s\" --windowsNetStart", _instanceDir, relativePath); // launch the command debug("doStartApplication attempting to spawn '%s'", command); if (spawn(command, FALSE) != -1) { // Try to see if server is really running int nTries = 10; BOOL running = FALSE; debug("doStartApplication: the spawn of the process worked."); debug("Command:"); debug(command); debug("doStartApplication: the spawn of the process worked. Command: '%s'", command); // Wait to be able to launch the java process in order it to free the lock // on the file. debug("Sleeping for 3 seconds to allow the process to free the lock."); Sleep(3000); while ((nTries > 0) && !running) { nTries--; if (isServerRunning(&running) != SERVICE_RETURN_OK) { break; } if (!running) { debug("Sleeping for 2 seconds to allow the process to free the lock. %d tries remaining.", nTries); Sleep(2000); } nTries--; } if (running) { @@ -695,10 +650,12 @@ { // failed to get the path of the executable file returnValue = SERVICE_RETURN_ERROR; debug("Could not get the path of the executable file.\n"); debug("Could not get the path of the executable file."); } else { debug("When determining the service bin path, the module file name is '%s'.", fileName); if (result == MAX_PATH) { // buffer was too small, executable name is probably not valid @@ -707,7 +664,7 @@ } else { if (strlen(fileName) + strlen(" start ") + strlen(_instanceDir) if ((strlen(fileName) + strlen(" start ") + strlen(_instanceDir) + strlen("\"\"")) < COMMAND_SIZE) { sprintf(serviceBinPath, "%s start \"%s\"", fileName, @@ -715,10 +672,11 @@ } else { char * msg = "The name of the resulting windows service command is too long.\n"; debug(msg); // buffer was too small, executable name is probably not valid returnValue = SERVICE_RETURN_ERROR; fprintf(stdout, "The name of the resulting windows service command is too long.\n"); fprintf(stdout, msg); } } } @@ -745,6 +703,11 @@ // retrieve list of services ServiceDescriptor* serviceList = NULL; int nbServices = -1; strcpy(serviceName, ""); debug("Attempting to get the service name assuming command to run is '%s'.", cmdToRun); returnValue = getServiceList(&serviceList, &nbServices); // go through the list of services and search for the service name @@ -772,8 +735,7 @@ } else { debug("The service name found is too long:"); debug(curService.serviceName); debug("The service name found is too long: '%s'", curService.serviceName); } break; } @@ -786,6 +748,9 @@ { debug("getServiceName: could not get service list."); } debug("The service name was found to be '%s'.", serviceName); return returnValue; } // getServiceName @@ -817,6 +782,8 @@ { ServiceReturnCode returnValue; // elaborate service type: // SERVICE_WIN32_OWN_PROCESS means this is not a driver and there is // only one service in the process @@ -832,8 +799,14 @@ DWORD controls; SERVICE_STATUS serviceStatus; BOOL success; debug("Updating the service status. statusToSet=%d win32ExitCode=%d serviceExitCode=%d checkPoint=%d waitHint=%d", statusToSet, win32ExitCode, serviceExitCode, checkPoint, waitHint); if (statusToSet == SERVICE_START_PENDING) { debug("Service start pending."); // do not accept any command when the service is starting up... controls = SERVICE_ACCEPT_NONE; } @@ -864,6 +837,7 @@ if (!success) { debugError("Failed to set the service status. Last error = %d.", GetLastError()); returnValue = SERVICE_RETURN_ERROR; } else @@ -897,6 +871,8 @@ DWORD checkPoint = CHECKPOINT_FIRST_VALUE; SERVICE_STATUS_HANDLE serviceStatusHandle; // __debugbreak(); debug("serviceMain called."); code = createServiceBinPath(cmdToRun); @@ -997,6 +973,7 @@ break; default: debugError("doApplication() failed"); code = SERVICE_RETURN_ERROR; _serviceCurStatus = SERVICE_STOPPED; updateServiceStatus ( @@ -1027,7 +1004,9 @@ // if all is ok wait for the application to die before we leave if (code == SERVICE_RETURN_OK) { debug("Waiting indefinitely for the application to exit."); WaitForSingleObject (_terminationEvent, INFINITE); debug("The application has exited."); } // update the service status to STOPPED if it's not already done @@ -1044,6 +1023,7 @@ _serviceStatusHandle ); } debug("serviceMain() returning."); } // serviceMain @@ -1054,6 +1034,7 @@ // ---------------------------------------------------- void doTerminateService(HANDLE terminationEvent) { debug("Faking a service termination so serviceMain can return."); SetEvent(terminationEvent); return; @@ -1071,17 +1052,17 @@ ServiceReturnCode code; DWORD checkpoint; BOOL running; debug("serviceHandler called."); debug("serviceHandler called with controlCode=%d.", controlCode); switch (controlCode) { case SERVICE_CONTROL_SHUTDOWN: // If system is shuting down then stop the service // -> no break here debug("serviceHandler: Shutdown."); debug("serviceHandler: shutdown"); case SERVICE_CONTROL_STOP: { // update service status to STOP_PENDING debug("serviceHandler: Stop."); debug("serviceHandler: stop"); _serviceCurStatus = SERVICE_STOP_PENDING; checkpoint = CHECKPOINT_FIRST_VALUE; updateServiceStatus ( @@ -1123,6 +1104,7 @@ { WORD argCount = 1; const char *argc[] = {_instanceDir}; debug("The server could not be stopped."); // We could not stop the server reportLogEvent( EVENTLOG_ERROR_TYPE, @@ -1222,7 +1204,11 @@ ); } if (myService != NULL) if (myService == NULL) { debugError("Failed to open the service '%s'.", serviceName); } else { while (!getConfigOk) { @@ -1240,7 +1226,7 @@ DWORD errCode = GetLastError(); if (errCode == ERROR_INSUFFICIENT_BUFFER) { // buffer nor big enough... // buffer not big enough... configSize += bytesNeeded; serviceConfig = (LPQUERY_SERVICE_CONFIG)realloc(serviceConfig, configSize); @@ -1248,12 +1234,7 @@ } else { char msg[200]; sprintf(msg, "getBinaryPath: error calling QueryServiceConfig. Code [%d]", errCode); // error debug(msg); debug("getBinaryPath: error calling QueryServiceConfig. Code [%d]", errCode); break; } } @@ -1266,12 +1247,7 @@ } else { debug( "getBinaryPath: the length of the binary path name is too big."); debug("serviceName:"); debug(serviceName); debug("binary path:"); debug(serviceConfig->lpBinaryPathName); debug("getBinaryPath: the length of the binary path name is too big. serviceName='%s', binaryPath='%s'", serviceName, serviceConfig->lpBinaryPathName); } } } @@ -1329,11 +1305,7 @@ DWORD lastError = GetLastError(); if (lastError != ERROR_MORE_DATA) { char msg[200]; sprintf(msg, "getServiceList: generic error. Code [%d]", lastError); // error debug(msg); debug("getServiceList: generic error. Code [%d]", lastError); returnValue = SERVICE_RETURN_ERROR; } else @@ -1359,10 +1331,8 @@ DWORD lastError = GetLastError(); if (lastError != ERROR_MORE_DATA) { char msg[200]; returnValue = SERVICE_RETURN_ERROR; sprintf(msg, "getServiceList: second try generic error. Code [%d]", lastError); debug("getServiceList: second try generic error. Code [%d]", lastError); } else { @@ -1406,18 +1376,17 @@ l = (ServiceDescriptor*)calloc(sizeof(ServiceDescriptor), aux); for (i = 0; i < aux; i++) { l[i].serviceName = strdup(curService->lpServiceName); l[i].displayName = strdup(curService->lpDisplayName); l[i].serviceName = _strdup(curService->lpServiceName); l[i].displayName = _strdup(curService->lpDisplayName); if (getBinaryPathName(scm, l[i].serviceName, binPath) == SERVICE_RETURN_OK) { l[i].cmdToRun = strdup(binPath); l[i].cmdToRun = _strdup(binPath); } else else { debug("Error getting binary path name of service:"); debug(l[i].serviceName); debug("Error getting binary path name of service: %s", l[i].serviceName); } curService++; } @@ -1457,6 +1426,8 @@ int nbServices = -1; int i; debug("Determining if service name '%s' is in use.", serviceName); // go through the list of services and search for the service name if (getServiceList(&serviceList, &nbServices) == SERVICE_RETURN_OK) { @@ -1477,6 +1448,7 @@ if (strcmp (serviceName, curService.serviceName) == 0) { // found the service! debug("The service name '%s' is in use.", serviceName); returnValue = SERVICE_IN_USE; } } @@ -1486,6 +1458,7 @@ } else { debugError("Could not determine if the service name '%s' is in use because listing the services failed.", serviceName); returnValue = SERVICE_RETURN_ERROR; } return returnValue; @@ -1509,6 +1482,7 @@ int i = 1; BOOL ended = FALSE; ServiceReturnCode nameInUseResult; strcpy(serviceName, ""); while (!ended) { if (i == 1) @@ -1540,6 +1514,9 @@ } } debug("createServiceName returning serviceName='%s' and returnValue=%d", serviceName, returnValue); return returnValue; } // createServiceName @@ -1586,6 +1563,7 @@ if (returnValue == SERVICE_RETURN_OK) { debug("Creating the service '%s'.", serviceName); myService = CreateService( scm, serviceName, // name of service @@ -1607,6 +1585,7 @@ if ((returnValue == SERVICE_RETURN_OK) && (myService == NULL)) { DWORD errCode = GetLastError(); debugError("Failed to create the service '%s'. Last error = %d.", serviceName, errCode); if (errCode == ERROR_DUPLICATE_SERVICE_NAME) { returnValue = DUPLICATED_SERVICE_NAME; @@ -1635,6 +1614,7 @@ if (!success) { debugError("Failed to add a description to the service '%s'. Last error = %d.", serviceName, GetLastError()); returnValue = SERVICE_RETURN_ERROR; } } @@ -1656,6 +1636,8 @@ free (serviceName); } debug("createServiceInScm returning %d.", returnValue); return returnValue; } // createServiceInScm @@ -1675,6 +1657,8 @@ SC_HANDLE myService = NULL; SERVICE_STATUS serviceStatus; debug("Removing service '%s' from the Service Control Manager.", serviceName); returnValue = openScm(GENERIC_WRITE, &scm); // open the service @@ -1687,6 +1671,7 @@ ); if (myService == NULL) { debugError("Failed to open the service '%s'. Last error = %d", serviceName, GetLastError()); returnValue = SERVICE_RETURN_ERROR; } } @@ -1699,6 +1684,7 @@ ); if (!success) { debugError("Failed to query the status for service '%s'. Last error = %d", serviceName, GetLastError()); returnValue = SERVICE_RETURN_ERROR; } } @@ -1708,7 +1694,9 @@ { if (serviceStatus.dwCurrentState != SERVICE_STOPPED) { BOOL success = ControlService ( BOOL success; debug("Attempting to stop the service '%s'.", serviceName); success = ControlService ( myService, SERVICE_CONTROL_STOP, &serviceStatus @@ -1716,6 +1704,7 @@ if (!success) { DWORD errCode = GetLastError(); debugError("Failed to stop the service '%s'. Last error = %d.", serviceName, errCode); if (errCode == ERROR_SERVICE_MARKED_FOR_DELETE) { returnValue = SERVICE_MARKED_FOR_DELETION; @@ -1735,11 +1724,13 @@ // remove the service if (returnValue == SERVICE_RETURN_OK) { BOOL success = DeleteService (myService); BOOL success; debug("Deleting the service '%s'."); success = DeleteService (myService); if (!success) { DWORD errCode = GetLastError(); debugError("Failed to delete the service '%s'. Last error = %d.", serviceName, errCode); if (errCode == ERROR_SERVICE_MARKED_FOR_DELETE) { returnValue = SERVICE_MARKED_FOR_DELETION; @@ -1784,7 +1775,7 @@ char cmdToRun[COMMAND_SIZE]; ServiceReturnCode code; debug("Creating service."); debug("Creating service displayName='%s' description='%s'.", displayName, description); code = createServiceBinPath(cmdToRun); if (code == SERVICE_RETURN_OK) @@ -1793,6 +1784,7 @@ code = getServiceName(cmdToRun, serviceName); if (code == SERVICE_RETURN_OK) { debug("Service '%s' already exists.", displayName); // There is a valid serviceName for the command to run, so // OpenDS is registered as a service. code = SERVICE_ALREADY_EXISTS; @@ -1800,6 +1792,7 @@ } else { debug("Could not find service '%s', so creating it now.", displayName); // We could not find a serviceName for the command to run, so // try to create the service. code = createServiceInScm(displayName, description, cmdToRun); @@ -1812,7 +1805,7 @@ } else { debug("Could not get a service name for command to run"); debug("Could not get a service name for command to run."); } } } @@ -1859,24 +1852,27 @@ char serviceName[MAX_SERVICE_NAME]; ServiceReturnCode code; strcpy(serviceName, ""); debug("Getting service state."); code = createServiceBinPath(cmdToRun); debug("Created the service bin path. code=%d. cmdToRun='%s'.", code, cmdToRun); if (code == SERVICE_RETURN_OK) { code = getServiceName(cmdToRun, serviceName); if (code == SERVICE_RETURN_OK) { // There is a valid serviceName for the command to run, so // OpenDS is registered as a service. fprintf(stdout, serviceName); returnCode = 0; debug("Service is enabled."); debug("Service '%s' is enabled.", serviceName); } else { returnCode = 1; debug("Service is disabled."); debug("Service '%s' is disabled enabled.", serviceName); } } else @@ -1950,6 +1946,7 @@ char serviceName[MAX_SERVICE_NAME]; ServiceReturnCode code; debug("removeService()"); code = createServiceBinPath(cmdToRun); if (code == SERVICE_RETURN_OK) @@ -1969,6 +1966,7 @@ returnCode = 2; } debug("removeService() returning %d.", returnCode); return returnCode; } // removeService @@ -1987,6 +1985,7 @@ char cmdToRun[COMMAND_SIZE]; ServiceReturnCode code; debug("startService()"); code = createServiceBinPath(cmdToRun); if (code == SERVICE_RETURN_OK) @@ -2042,6 +2041,7 @@ WIN_EVENT_ID_SERVER_START_FAILED, argCount, argc ); debugError("For instance dir '%s', %s", argc[0], argc[1]); } deregisterEventLog(); } @@ -2063,29 +2063,22 @@ } // startService // --------------------------------------------------------------- // Function called to know if the --debug option was passed // when calling this executable or not. The DEBUG variable is // updated accordingly. // --------------------------------------------------------------- void updateDebugFlag(char* argv[], int argc, int startIndex) { int i; DEBUG = FALSE; for (i=startIndex; (i<argc) && !DEBUG; i++) { if (strcmp(argv[i], "--debug") == 0) { DEBUG = TRUE; } } } int main(int argc, char* argv[]) { char* subcommand; int returnCode = 0; int i; updateDebugFlag(argv, argc); debug("main called."); for (i = 0; i < argc; i++) { debug(" argv[%d] = '%s'", i, argv[i]); } // __debugbreak(); if (argc <= 1) { fprintf(stdout, @@ -2105,8 +2098,7 @@ } else { _instanceDir = strdup(argv[2]); updateDebugFlag(argv, argc, 5); _instanceDir = _strdup(argv[2]); returnCode = createService(argv[3], argv[4]); free(_instanceDir); } @@ -2121,8 +2113,7 @@ } else { _instanceDir = strdup(argv[2]); updateDebugFlag(argv, argc, 3); _instanceDir = _strdup(argv[2]); returnCode = serviceState(); free(_instanceDir); } @@ -2137,8 +2128,7 @@ } else { _instanceDir = strdup(argv[2]); updateDebugFlag(argv, argc, 3); _instanceDir = _strdup(argv[2]); returnCode = removeService(); free(_instanceDir); } @@ -2153,8 +2143,7 @@ } else { _instanceDir = strdup(argv[2]); DEBUG = TRUE; _instanceDir = _strdup(argv[2]); returnCode = startService(); free(_instanceDir); } @@ -2171,8 +2160,7 @@ { BOOL running; ServiceReturnCode code; _instanceDir = strdup(argv[2]); updateDebugFlag(argv, argc, 3); _instanceDir = _strdup(argv[2]); code = isServerRunning(&running); if (code == SERVICE_RETURN_OK) { @@ -2196,8 +2184,7 @@ } else { char* serviceName = strdup(argv[2]); updateDebugFlag(argv, argc, 3); char* serviceName = _strdup(argv[2]); returnCode = removeServiceWithServiceName(serviceName); free(serviceName); } @@ -2210,6 +2197,8 @@ } } debug("main returning %d.", returnCode); return returnCode; } // main opends/src/build-tools/windows/service.h
@@ -25,12 +25,12 @@ * Portions Copyright 2007 Sun Microsystems, Inc. */ #include "common.h" #include <errno.h> #include <fcntl.h> #include <io.h> #include <stdio.h> #include <sys/locking.h> #include "common.h" #include "EventLogMsg.h" #define MAX_SERVICE_NAME 256 opends/src/build-tools/windows/winlauncher.c
@@ -27,7 +27,6 @@ #include "winlauncher.h" // ---------------------------------------------------- // Generates the pid file name for a given instanceDir. // Returns TRUE if the command name could be initiated and @@ -38,13 +37,18 @@ { BOOL returnValue; char* relativePath = "\\logs\\server.pid"; debug("Attempting to get the PID file for instanceDir='%s'", instanceDir); if ((strlen(relativePath) + strlen(instanceDir)) < maxSize) { sprintf(pidFile, "%s\\logs\\server.pid", instanceDir); sprintf(pidFile, maxSize, "%s\\logs\\server.pid", instanceDir); returnValue = TRUE; debug("PID file name is '%s'.", pidFile); } else { debugError("Unable to get the PID file name because the path was too long."); returnValue = FALSE; } return returnValue; @@ -68,7 +72,9 @@ { returnValue = TRUE; } debug("File '%s' does%s exist.", fileName, (returnValue ? "" : " not")); return returnValue; } // fileExists @@ -84,23 +90,28 @@ char pidFile[PATH_SIZE]; int nTries = 10; debug("Attempting to delete the PID file from instanceDir='%s'.", instanceDir); // Sometimes the lock on the system in windows takes time to be released. if (getPidFile(instanceDir, pidFile, PATH_SIZE)) { while (fileExists(pidFile) && (nTries > 0) && !returnValue) { debug("PID file '%s' exists, attempting to remove it.", instanceDir); if (remove(pidFile) == 0) { debug("Successfully removed PID file: '%s'.", pidFile); returnValue = TRUE; } else { Sleep(500); nTries--; debug("Failed to remove the PID file. Sleeping for a bit. Will try %d more time(s).", nTries); Sleep(500); } } } debug("deletePidFile('%s') returning %d.", instanceDir, returnValue); return returnValue; } // deletePidFile @@ -118,11 +129,13 @@ char buf[BUF_SIZE]; int read; debug("Attempting to get the PID for the server rooted at '%s'.", instanceDir); if (getPidFile(instanceDir, pidFile, PATH_SIZE)) { if ((f = fopen(pidFile, "r")) != NULL) { read = fread(buf, 1, sizeof(buf),f); debug("Read '%s' from the PID file '%s'.", buf, pidFile); } if (f != NULL) @@ -132,7 +145,9 @@ } else { fprintf(stderr, "File %s could not be opened", pidFile); char * msg = "File %s could not be opened.\nMost likely the server has already stopped.\n\n"; debug(msg, pidFile); fprintf(stderr, msg, pidFile); returnValue = 0; } } @@ -140,6 +155,7 @@ { returnValue = 0; } debug("getPid('%s') returning %d.", instanceDir, returnValue); return returnValue; } // getPid @@ -152,7 +168,12 @@ BOOL killProcess(int pid) { BOOL processDead; HANDLE procHandle = OpenProcess( HANDLE procHandle; debug("killProcess(pid=%d)", pid); debug("Opening process with pid=%d.", pid); procHandle = OpenProcess( PROCESS_TERMINATE // to terminate the process | PROCESS_QUERY_INFORMATION, // to get exit code FALSE, // handle is not inheritable @@ -161,6 +182,7 @@ if (procHandle == NULL) { debug("The process with pid=%d has already terminated.", pid); // process already dead processDead = TRUE; } @@ -168,14 +190,17 @@ { if (!TerminateProcess(procHandle, 0)) { debugError("Failed to terminate process (pid=%d) lastError=%d.", pid, GetLastError()); // failed to terminate the process processDead = FALSE; } else { // wait for the process to end. DWORD exitCode; int nTries = 20; debug("Successfully began termination process for (pid=%d).", pid); // wait for the process to end. processDead = FALSE; while ((nTries > 0) && !processDead) @@ -184,18 +209,21 @@ if (exitCode == STILL_ACTIVE) { // process is still alive, let's wait 1 sec and loop again Sleep(1000); nTries--; debug("Process (pid=%d) has not yet exited. Sleeping for 1 second and will try %d more time(s).", pid, nTries); Sleep(1000); } else { debug("Process (pid=%d) has exited with exit code %d.", pid, exitCode); processDead = TRUE; } } } CloseHandle(procHandle); } debug("killProcess(pid=%d) returning %d", pid, processDead); return processDead; } // killProcess @@ -206,11 +234,13 @@ // otherwise. // ---------------------------------------------------- BOOL createPidFile(const char* instanceDir, int pid) { { BOOL returnValue = FALSE; char pidFile[PATH_SIZE]; FILE *f; debug("createPidFile(instanceDir='%s',pid=%d)", instanceDir, pid); if (getPidFile(instanceDir, pidFile, PATH_SIZE)) { if ((f = fopen(pidFile, "w")) != NULL) @@ -218,14 +248,17 @@ fprintf(f, "%d", pid); fclose (f); returnValue = TRUE; debug("Successfully put pid=%d in the pid file '%s'.", pid, pidFile); } else { debugError("Couldn't create the pid file '%s' because the file could not be opened.", pidFile); returnValue = FALSE; } } else { debugError("Couldn't create the pid file because the pid file name could not be constructed."); returnValue = FALSE; } @@ -246,7 +279,14 @@ int curCmdInd = 0; int i = 0; BOOL overflow = FALSE; debug("Constructing full command line from arguments:"); for (i = 0; (argv[i] != NULL); i++) { debug(" argv[%d]: %s", i, argv[i]); } i = 0; while ((argv[i] != NULL) && !overflow) { const char* curarg = argv[i++]; @@ -319,6 +359,15 @@ } } } if (overflow) { debugError("Failed to construct the full commandline because the buffer wasn't big enough."); } else { debug("The full commandline is '%s'.", command); } return !overflow; } // getCommandLine @@ -350,7 +399,7 @@ int childPid; char command[COMMAND_SIZE]; if (getCommandLine(argv, command, COMMAND_SIZE)) { childPid = spawn(command, TRUE); @@ -362,11 +411,13 @@ } else { debugError("Couldn't start the child process because the spawn failed."); returnValue = -1; } } else { debugError("Couldn't start the child process because the full command line could not be constructed."); returnValue = -1; } @@ -401,6 +452,8 @@ int childPid; debug("Attempting to stop the server running at root '%s'.", instanceDir); childPid = getPid(instanceDir); if (childPid != 0) @@ -411,7 +464,11 @@ deletePidFile(instanceDir); } } else { debug("Could not stop the server running at root '%s' because the pid could not be located.", instanceDir); } return returnCode; } // stop @@ -450,9 +507,18 @@ if (getCommandLine(argv, command, COMMAND_SIZE)) { returnValue = spawn(command, TRUE); if (returnValue <= 0) { debugError("Failed to launch the child process '%s'.", command); } else { debug("Successfully launched the child process '%s'.", command); } } else { debugError("Couldn't launch the child process because the full command line could not be constructed."); returnValue = -1; } @@ -471,9 +537,25 @@ int main(int argc, char* argv[]) { int returnCode; char* subcommand = argv[1]; char* instanceDir = argv[2]; char* subcommand = NULL; char* instanceDir = NULL; int i; debug("main called."); for (i = 0; i < argc; i++) { debug(" argv[%d] = '%s'", i, argv[i]); } if (argc < 3) { char * msg = "Expected command line args of [subcommand] [server directory], but got %d arguments.\n"; debugError(msg, argc - 1); fprintf(stderr, msg, argc - 1); return -1; } subcommand = argv[1]; instanceDir = argv[2]; argv += 3; if (strcmp(subcommand, "start") == 0) @@ -490,9 +572,12 @@ } else { fprintf(stderr, "Unknown subcommand: [%s]", subcommand); char * msg = "Unknown subcommand: [%s]\n"; debugError(msg, argc - 1); fprintf(stderr, msg, subcommand); returnCode = -1; } debug("main finished. Returning %d", returnCode); return returnCode; } opends/src/build-tools/windows/winlauncher.h
@@ -25,11 +25,11 @@ * Portions Copyright 2007 Sun Microsystems, Inc. */ #include "common.h" #include <stdio.h> #include <stdlib.h> #include <sys/stat.h> #include <process.h> #include "common.h" #define PATH_SIZE 1024 #define BUF_SIZE 1024