From 98e131bb4dde9eb6e2befce74256f5caa2eb093b Mon Sep 17 00:00:00 2001
From: ludovicp <ludovicp@localhost>
Date: Thu, 27 May 2010 09:52:42 +0000
Subject: [PATCH] Fix for issue #4554 - Potential problems using Windows Service during startup. The fix consists on waiting in the service code to the start-ds.bat call to finish (the re-entrant one). This avoids having a race condition problem locking the file (as can happen today). There is a new environment variable that can be configured (OPENDS_WINDOWS_SERVICE_STARTDS_WAIT). The default value is 300000 milliseconds (5 minutes). This is the maximum time in milliseconds the service code will wait for the server to start before checking directly its status. Also update setup.bat and uninstall.bat to return an error code when called in CLI mode.
---
opends/src/build-tools/windows/common.c | 121 ++++++++++++++++++++++++++++++++++++++--
1 files changed, 114 insertions(+), 7 deletions(-)
diff --git a/opends/src/build-tools/windows/common.c b/opends/src/build-tools/windows/common.c
index 3974748..db1d407 100644
--- a/opends/src/build-tools/windows/common.c
+++ b/opends/src/build-tools/windows/common.c
@@ -22,10 +22,11 @@
* CDDL HEADER END
*
*
-* Copyright 2008 Sun Microsystems, Inc.
+* Copyright 2008-2010 Sun Microsystems, Inc.
*/
#include "common.h"
+#include "service.h"
#include <errno.h>
#include <fcntl.h>
#include <io.h>
@@ -56,7 +57,8 @@
HANDLE hStdout; /* stdout */
HANDLE hStderr; /* stderr */
- debug("Attempting to create child process '%s' background=%d.", command,
+ debug("createChildProcess: Attempting to create child process '%s' background=%d.",
+ command,
background);
// reset process info first
@@ -91,29 +93,95 @@
if (createOk)
{
- debug("Successfully created child process '%s'.", command);
+ debug("createChildProcess: Successfully created child process '%s'.", command);
}
else
{
- debugError("Failed to create child process '%s'. Last error = %d.",
+ debugError(
+ "createChildProcess: Failed to create child process '%s'. Last error = %d.",
command, GetLastError());
}
return createOk;
} // createChildProcess
+BOOL createBatchFileChildProcess(char* batchFile, BOOL background,
+PROCESS_INFORMATION* procInfo)
+{
+ BOOL createOk;
+ STARTUPINFO startInfo; // info to pass to the new process
+ DWORD processFlag; // background process flag
+ HANDLE hStdin; /* stdin */
+ HANDLE hStdout; /* stdout */
+ HANDLE hStderr; /* stderr */
+ char command[COMMAND_SIZE]; // full command line
+
+ if (strlen(batchFile) + 3 >= COMMAND_SIZE)
+ {
+ debug("createBatchFileChildProcess: the batch file path is too long.");
+ return FALSE;
+ }
+ sprintf(command, "/c %s", batchFile);
+ debug("createBatchFileChildProcess: Attempting to create child process '%s' background=%d.",
+ command,
+ background);
+
+ // reset process info first
+ ZeroMemory(procInfo, sizeof(PROCESS_INFORMATION));
+
+ // initialize handles to pass to the child process
+ ZeroMemory(&startInfo, sizeof(STARTUPINFO));
+ startInfo.cb = sizeof(STARTUPINFO);
+ startInfo.dwFlags |= STARTF_USESTDHANDLES; // use handles above
+
+ hStdin= GetStdHandle(STD_INPUT_HANDLE);
+ SetHandleInformation (hStdin, HANDLE_FLAG_INHERIT, FALSE);
+ hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
+ SetHandleInformation (hStdout, HANDLE_FLAG_INHERIT, FALSE);
+ hStderr = GetStdHandle(STD_ERROR_HANDLE);
+ SetHandleInformation (hStderr, HANDLE_FLAG_INHERIT, FALSE);
+
+ // Create the child process
+ processFlag = background == TRUE ? DETACHED_PROCESS : 0;
+ createOk = CreateProcess(
+ "cmd.exe", // 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("createBatchFileChildProcess: Successfully created child process '%s'.", command);
+ }
+ else
+ {
+ debugError("createBatchFileChildProcess: Failed to create child process '%s'. Last error = %d.",
+ command, GetLastError());
+ }
+
+ return createOk;
+} // createChildProcess
+
+
// ----------------------------------------------------
// Function used to launch a process for the given command
// If the process could be created it returns the pid of
// the created process and -1 otherwise.
// ----------------------------------------------------
-int spawn(const char* command, BOOL background)
+int spawn(char* command, BOOL background)
{
DWORD childPid = -1; // child's pid
PROCESS_INFORMATION procInfo; // info on the new process
BOOL createOk;
- createOk = createChildProcess((char*)command, background, &procInfo);
+ createOk = createChildProcess(command, background, &procInfo);
if(createOk)
{
@@ -132,7 +200,46 @@
}
} // spawn
-
+// ----------------------------------------------------
+// Function used to wait for a process.
+// The passed waitTime parameter is maximum the time in milliseconds to wait.
+// Returns TRUE if the process ended and updates the exitCode
+// parameter with the return value of the process.
+// Returns FALSE if the process did not end with the provided
+// timeout and the error code returned by WaitForSingleObject
+// in the provided exitCode value.
+// ----------------------------------------------------
+BOOL waitForProcess(PROCESS_INFORMATION* procInfo, DWORD waitTime,
+ DWORD* exitCode)
+{
+ BOOL returnValue = TRUE;
+ DWORD waitForSingleCode;
+ debug("waitForProcess: wait time is: %d", waitTime);
+ waitForSingleCode = WaitForSingleObject (procInfo->hProcess, waitTime);
+ if (waitForSingleCode == WAIT_OBJECT_0)
+ {
+ debug("waitForProcess: was successful");
+ GetExitCodeProcess(procInfo->hProcess, exitCode);
+ debug("waitForProcess exitCode: %d", *exitCode);
+ }
+ else
+ {
+ returnValue = FALSE;
+ switch (waitForSingleCode)
+ {
+ case WAIT_FAILED:
+ debug("waitForProcess: Wait for process failed: %d", GetLastError());
+ break;
+ case WAIT_TIMEOUT:
+ debug("waitForProcess: Process timed out.");
+ break;
+ default:
+ debug("waitForProcess: WaitForSingleObject returned %d", waitForSingleCode);
+ }
+ *exitCode = waitForSingleCode;
+ }
+ return returnValue;
+}
// ---------------------------------------------------
// Debug utility.
// ---------------------------------------------------
--
Gitblit v1.10.0