mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

jvergara
18.09.2010 7bf55dfdb8dd25390198a0a9078b2ecf3417b9be
Fix for issue 4084 (Windows Service doesn't detect start-ds failure)
Improve the code of windows service to poll the status of the server (whether is running or not).
Improve some of the messages associated with the events that are sent to the windows service log.
Improve the code that is in charge of starting the service (and the server) to help identify cases where the server startup is correctly launched but the startup itself fails (because for instance a port of the server is already in use).
5 files modified
255 ■■■■■ changed files
opends/lib/launcher_administrator.exe patch | view | raw | blame | history
opends/lib/opends_service.exe patch | view | raw | blame | history
opends/lib/winlauncher.exe patch | view | raw | blame | history
opends/src/build-tools/windows/EventLogMsg.mc 11 ●●●● patch | view | raw | blame | history
opends/src/build-tools/windows/service.c 244 ●●●●● patch | view | raw | blame | history
opends/lib/launcher_administrator.exe
Binary files differ
opends/lib/opends_service.exe
Binary files differ
opends/lib/winlauncher.exe
Binary files differ
opends/src/build-tools/windows/EventLogMsg.mc
@@ -22,7 +22,7 @@
; * CDDL HEADER END
; *
; *
; *      Copyright 2008 Sun Microsystems, Inc.
; *      Copyright 2008-2010 Sun Microsystems, Inc.
; */
;/*
; * ==========================================================================
@@ -100,4 +100,11 @@
Language     = English
%1
.
MessageId    = 0x6
Severity     = Error
Facility     = OPENDS
SymbolicName = WIN_EVENT_ID_SERVER_STOPPED_OUTSIDE_SCM
Language     = English
OpenDS stopped outside the Service Control Manager.
OpenDS is in %1.
.
opends/src/build-tools/windows/service.c
@@ -13,7 +13,7 @@
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at
* file and include the License file \
* trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
* add the following below this CDDL HEADER, with the fields enclosed
* by brackets "[]" replaced with your own identifying * information:
@@ -22,7 +22,7 @@
* CDDL HEADER END
*
*
*      Copyright 2008 Sun Microsystems, Inc.
*      Copyright 2008-2010 Sun Microsystems, Inc.
*/
#include "service.h"
@@ -427,32 +427,43 @@
// The functions returns SERVICE_RETURN_OK if we could determine if
// the server is running or not and false otherwise.
// ----------------------------------------------------
ServiceReturnCode isServerRunning(BOOL *running)
ServiceReturnCode isServerRunning(BOOL *running, BOOL mustDebug)
{
  ServiceReturnCode returnValue;
  char* relativePath = "\\locks\\server.lock";
  char lockFile[MAX_PATH];
  debug("Determining if the server is running.");
  if (mustDebug)
  {
    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'.",
    if (mustDebug)
    {
      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);
      if (mustDebug)
      {
        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);
        if (mustDebug)
        {
          debug("Able to lock '%s', so the server is not running.", lockFile);
        }
        *running = FALSE;
        _locking(fd, LK_UNLCK, 1);
      }
@@ -460,7 +471,10 @@
      {
        if (errno == EACCES)
        {
          debug("Unable to lock '%s', so the server is running.", lockFile);
          if (mustDebug)
          {
            debug("Unable to lock '%s', so the server is running.", lockFile);
          }
          *running = TRUE;
        }
        else
@@ -474,15 +488,18 @@
    }
    else
    {
      debug("Could not open lock file '%s', which means the server is not running.",
          lockFile);
      if (mustDebug)
      {
        debug("Could not open lock file '%s', which means the server is not running.",
            lockFile);
      }
      *running = FALSE;
      returnValue = SERVICE_RETURN_ERROR;
    }
  }
  else
  {
    debug("Lock file path is too long.");
    debugError("Lock file path is too long.");
    *running = FALSE;
    returnValue = SERVICE_RETURN_ERROR;
  }
@@ -520,11 +537,11 @@
      BOOL running = FALSE;
      if (nTriesEnv != NULL)
      {
        nTries = (int)strtol(nTriesEnv, (char **)NULL, 10);
        if (nTries <= 0)
        {
          nTries = 100;
        }
        nTries = (int)strtol(nTriesEnv, (char **)NULL, 10);
        if (nTries <= 0)
        {
          nTries = 100;
        }
      }
      else
      {
@@ -541,7 +558,7 @@
      while ((nTries > 0) && !running)
      {
        nTries--;
        if (isServerRunning(&running) != SERVICE_RETURN_OK)
        if (isServerRunning(&running, TRUE) != SERVICE_RETURN_OK)
        {
          break;
        }
@@ -607,7 +624,7 @@
      Sleep(3000);
      while ((nTries > 0) && running)
      {
        if (isServerRunning(&running) != SERVICE_RETURN_OK)
        if (isServerRunning(&running, TRUE) != SERVICE_RETURN_OK)
        {
          break;
        }
@@ -817,7 +834,7 @@
  // elaborate the commands supported by the service:
  // - STOP        customer has performed a stop-ds (or NET STOP)
  // - SHUTDOWN    the system is rebooting
  // - INTERROGATE service controler can interogate the service
  // - INTERROGATE service controler can interrogate the service
  // - No need to support PAUSE/CONTINUE
  //
  // Note: INTERROGATE *must* be supported by the service handler
@@ -831,7 +848,7 @@
  if (statusToSet == SERVICE_START_PENDING)
  {
    debug("Service start pending.");
    debug("Service start pending: no controls accepted.");
    // do not accept any command when the service is starting up...
    controls = SERVICE_ACCEPT_NONE;
  }
@@ -896,6 +913,7 @@
  // a checkpoint value indicate the progress of an operation
  DWORD checkPoint = CHECKPOINT_FIRST_VALUE;
  SERVICE_STATUS_HANDLE serviceStatusHandle;
  BOOL running;
  // __debugbreak();
@@ -957,22 +975,13 @@
    );
  }
  // update the service status to START_PENDING
  if (code == SERVICE_RETURN_OK)
  if (isServerRunning(&running, TRUE) != SERVICE_RETURN_OK)
  {
    _serviceCurStatus = SERVICE_START_PENDING;
    updateServiceStatus (
    _serviceCurStatus,
    NO_ERROR,
    0,
    checkPoint++,
    TIMEOUT_START_SERVICE,
    _serviceStatusHandle
    );
    running = FALSE;
  }
  // start the application
  if (code == SERVICE_RETURN_OK)
  // start the application if not already started
  if (!running && code == SERVICE_RETURN_OK)
  {
    WORD argCount = 1;
    const char *argc[] = {_instanceDir};
@@ -981,21 +990,7 @@
    switch (code)
    {
      case SERVICE_RETURN_OK:
      // start is ok
      _serviceCurStatus = SERVICE_RUNNING;
      updateServiceStatus (
      _serviceCurStatus,
      NO_ERROR,
      0,
      CHECKPOINT_NO_ONGOING_OPERATION,
      TIMEOUT_NONE,
      _serviceStatusHandle
      );
      reportLogEvent(
      EVENTLOG_SUCCESS,
      WIN_EVENT_ID_SERVER_STARTED,
      argCount, argc
      );
      // start is ok: do nothing for the moment.
      break;
      default:
@@ -1003,53 +998,136 @@
      code = SERVICE_RETURN_ERROR;
      _serviceCurStatus = SERVICE_STOPPED;
      updateServiceStatus (
      _serviceCurStatus,
      ERROR_SERVICE_SPECIFIC_ERROR,
      -1,
      CHECKPOINT_NO_ONGOING_OPERATION,
      TIMEOUT_NONE,
      _serviceStatusHandle);
        _serviceCurStatus,
        ERROR_SERVICE_SPECIFIC_ERROR,
        -1,
        CHECKPOINT_NO_ONGOING_OPERATION,
        TIMEOUT_NONE,
        _serviceStatusHandle);
      reportLogEvent(
      EVENTLOG_ERROR_TYPE,
      WIN_EVENT_ID_SERVER_START_FAILED,
      argCount, argc
        EVENTLOG_ERROR_TYPE,
        WIN_EVENT_ID_SERVER_START_FAILED,
        argCount, argc
      );
    }
  }
  else
  {
    updateServiceStatus (
    _serviceCurStatus,
    ERROR_SERVICE_SPECIFIC_ERROR,
    0,
    CHECKPOINT_NO_ONGOING_OPERATION,
    TIMEOUT_NONE,
    _serviceStatusHandle);
      _serviceCurStatus,
      ERROR_SERVICE_SPECIFIC_ERROR,
      0,
      CHECKPOINT_NO_ONGOING_OPERATION,
      TIMEOUT_NONE,
      _serviceStatusHandle);
  }
  // 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.");
  }
    BOOL updatedRunningStatus = FALSE;
    DWORD returnValue;
    int refreshPeriodSeconds = 10;
    char *refreshPeriodEnv = getenv("OPENDS_WINDOWS_SERVICE_REFRESH_PERIOD");
    if (refreshPeriodEnv != NULL)
    {
      refreshPeriodSeconds = (int)strtol(refreshPeriodEnv, (char **)NULL, 10);
      if (refreshPeriodSeconds < 0)
      {
        refreshPeriodSeconds = 10;
      }
    }
    debug("Refresh period in seconds is %d.", refreshPeriodSeconds);
    while (TRUE)
    {
      if (refreshPeriodSeconds == 0 && updatedRunningStatus)
      {
        returnValue = WaitForSingleObject (_terminationEvent, INFINITE);
        break;
      }
      else
      {
        running = FALSE;
        if (updatedRunningStatus)
        {
          Sleep(5000);
        }
        else
        {
          returnValue = WaitForSingleObject (_terminationEvent,
                                           refreshPeriodSeconds * 1000);
          if (returnValue == WAIT_OBJECT_0)
          {
            debug("The application has exited.");
            break;
          }
        }
        code = isServerRunning(&running, FALSE);
        if (code != SERVICE_RETURN_OK)
        {
           debug("checking in serviceMain: error interrogating status.");
        }
        else if (running)
        {
          _serviceCurStatus = SERVICE_RUNNING;
          if (!updatedRunningStatus)
          {
            WORD argCount = 1;
            const char *argc[] = {_instanceDir};
            updateServiceStatus (
               _serviceCurStatus,
               NO_ERROR,
               0,
               checkPoint ++,
               TIMEOUT_NONE,
               _serviceStatusHandle
             );
             reportLogEvent(
               EVENTLOG_SUCCESS,
               WIN_EVENT_ID_SERVER_STARTED,
               argCount, argc
             );
             updatedRunningStatus = TRUE;
          }
        }
        else
        {
          WORD argCount = 1;
          const char *argc[] = {_instanceDir};
          _serviceCurStatus = SERVICE_STOPPED;
          debug("checking in serviceMain serviceHandler: service stopped.");
          updateServiceStatus (
              _serviceCurStatus,
              ERROR_SERVICE_SPECIFIC_ERROR,
              -1,
              CHECKPOINT_NO_ONGOING_OPERATION,
              TIMEOUT_NONE,
              _serviceStatusHandle);
          reportLogEvent(
              EVENTLOG_ERROR_TYPE,
              WIN_EVENT_ID_SERVER_STOPPED_OUTSIDE_SCM,
              argCount, argc);
          break;
        }
      }
    }
  }
  // update the service status to STOPPED if it's not already done
  if ((_serviceCurStatus != SERVICE_STOPPED) &&
    (_serviceStatusHandle != NULL))
     (_serviceStatusHandle != NULL))
  {
    _serviceCurStatus = SERVICE_STOPPED;
    updateServiceStatus (
    _serviceCurStatus,
    NO_ERROR,
    0,
    CHECKPOINT_NO_ONGOING_OPERATION,
    TIMEOUT_NONE,
    _serviceStatusHandle
    );
      _serviceCurStatus,
      NO_ERROR,
      0,
      CHECKPOINT_NO_ONGOING_OPERATION,
      TIMEOUT_NONE,
      _serviceStatusHandle
     );
  }
  debug("serviceMain() returning.");
   debug("serviceMain() returning.");
}  // serviceMain
@@ -1160,7 +1238,7 @@
    // ------------------------------
    case SERVICE_CONTROL_INTERROGATE:
      debug("serviceHandler: interrogate.");
      code = isServerRunning(&running);
      code = isServerRunning(&running, TRUE);
      if (code != SERVICE_RETURN_OK)
      {
        debug("serviceHandler: error interrogating.");
@@ -2065,19 +2143,19 @@
      {
        argc[1] =
        "startService: StartServiceCtrlDispatcher did not work: \
        ERROR_FAILED_SERVICE_CONTROLLER_CONNECT.";
ERROR_FAILED_SERVICE_CONTROLLER_CONNECT.";
      }
      else if (lastError == ERROR_INVALID_DATA)
      {
        argc[1] =
        "startService: StartServiceCtrlDispatcher did not work: \
        ERROR_INVALID_DATA.";
ERROR_INVALID_DATA.";
      }
      else if (lastError == ERROR_SERVICE_ALREADY_RUNNING)
      {
        argc[1] =
        "startService: StartServiceCtrlDispatcher did not work: \
        ERROR_SERVICE_ALREADY_RUNNING.";
ERROR_SERVICE_ALREADY_RUNNING.";
      }
      else
      {
@@ -2210,7 +2288,7 @@
        BOOL running;
        ServiceReturnCode code;
        _instanceDir = _strdup(argv[2]);
        code = isServerRunning(&running);
        code = isServerRunning(&running, TRUE);
        if (code == SERVICE_RETURN_OK)
        {
          returnCode = 0;