summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVladislav Vaintroub <vvaintroub@mysql.com>2008-11-14 02:01:41 +0100
committerVladislav Vaintroub <vvaintroub@mysql.com>2008-11-14 02:01:41 +0100
commitf2a610e1e072f3b50709be3f419ea3ac1d7a3aa5 (patch)
treedc2b286e5971664d1cad910fc946e7e50a7381b0
parent60d5e900891bc849d7a6180b708290fe7a3e93ab (diff)
downloadmariadb-git-f2a610e1e072f3b50709be3f419ea3ac1d7a3aa5.tar.gz
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. sql/mysqld.cc: Set service status to running after all initialization is complete sql/nt_servc.cc: New method SetRunning() to be called by application to set service status to SERVICE_RUNNING when apllication has finished initialization. sql/nt_servc.h: New method SetRunning() to be called by application when initialization completes
-rw-r--r--sql/mysqld.cc3
-rw-r--r--sql/nt_servc.cc12
-rw-r--r--sql/nt_servc.h14
3 files changed, 24 insertions, 5 deletions
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index c3e5449b22b..ba6c8c6169f 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -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();
diff --git a/sql/nt_servc.cc b/sql/nt_servc.cc
index a04f284a3de..e570898f373 100644
--- a/sql/nt_servc.cc
+++ b/sql/nt_servc.cc
@@ -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 @@ error:
return;
}
+
+void NTService::SetRunning()
+{
+ if (pService)
+ pService->SetStatus(SERVICE_RUNNING,NO_ERROR, 0, 0, 0);
+}
+
+
/* ------------------------------------------------------------------------
StartService() - starts the appliaction thread
-------------------------------------------------------------------------- */
diff --git a/sql/nt_servc.h b/sql/nt_servc.h
index a3c12569114..9b689e434e1 100644
--- a/sql/nt_servc.h
+++ b/sql/nt_servc.h
@@ -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;