Commit ea0efe45 authored by Vladislav Vaintroub's avatar Vladislav Vaintroub
Browse files

Bug #20430 mysqld.exe windows service stuck in "SERVICE_STOP_PENDING"

status

The problem appears to be a race condition, when service is being
stopped right after startup. We set the service status to SERVICE_RUNNING
way too early it cannot yet handle stop requests -  initialization has
not finished and  hEventShutdown  that signals server to stop is not yet
created. If somebody issues "net stop MySQL" at this time, MySQL is not
informed about the stop and continues to run as usual, while
NTService::ServiceMain() stucks forever waiting for mysql's "main" thread
to finish.

Solution is to remain in SERVICE_START_PENDING status until after server
initialization  is fully complete and only then change the status to
SERVICE_RUNNING. In  SERVICE_START_PENDING we do not accept service control
requests, i.e it is not possible to stop service in that time.
parent d60da1c2
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -3840,6 +3840,9 @@ we force server id to 2, but this MySQL server will not act as a slave.");
                                                       : mysqld_unix_port),
                         mysqld_port,
                         MYSQL_COMPILATION_COMMENT);
#if defined(_WIN32) && !defined(EMBEDDED_LIBRARY)
  Service.SetRunning();
#endif

#if defined(__NT__) || defined(HAVE_SMEM)
  handle_connections_methods();
+8 −4
Original line number Diff line number Diff line
@@ -245,10 +245,6 @@ void NTService::ServiceMain(DWORD argc, LPTSTR *argv)
  if (!pService->StartService())
    goto error;

  // Check that the service is now running.
  if (!pService->SetStatus(SERVICE_RUNNING,NO_ERROR, 0, 0, 0))
    goto error;

  // wait for exit event
  WaitForSingleObject (pService->hExitEvent, INFINITE);

@@ -264,6 +260,14 @@ void NTService::ServiceMain(DWORD argc, LPTSTR *argv)
  return;
}


void NTService::SetRunning()
{
  if (pService)
    pService->SetStatus(SERVICE_RUNNING,NO_ERROR, 0, 0, 0);
}


/* ------------------------------------------------------------------------
   StartService() - starts the appliaction thread
 -------------------------------------------------------------------------- */
+13 −1
Original line number Diff line number Diff line
@@ -56,7 +56,19 @@ class NTService
    BOOL IsService(LPCSTR ServiceName);
    BOOL got_service_option(char **argv, char *service_option);
    BOOL is_super_user();
    void Stop(void); //to be called from app. to stop service

    /* 
      SetRunning() is to be called by the application 
      when initialization completes and it can accept
      stop request
    */
    void SetRunning(void);

    /*
      Stop() is to be called by the application to stop 
      the service
    */
    void Stop(void); 

  protected:
    LPSTR		   ServiceName;