You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by ma...@apache.org on 2019/06/13 10:07:46 UTC

[commons-daemon] 05/05: Fix https://issues.apache.org/jira/browse/DAEMON-303

This is an automated email from the ASF dual-hosted git repository.

markt pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-daemon.git

commit 840e29005da54f82ba7ca49332bfe67bbd6b9dd0
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Thu Jun 13 11:06:43 2019 +0100

    Fix https://issues.apache.org/jira/browse/DAEMON-303
    
    Add an option to configure the service to start using the "Automatic
    (Delayed Start)" mode.
---
 src/changes/changes.xml                   |  6 +++-
 src/native/windows/apps/prunmgr/prunmgr.c | 32 ++++++++++++-----
 src/native/windows/apps/prunsrv/prunsrv.c |  9 ++++-
 src/native/windows/include/service.h      |  4 ++-
 src/native/windows/src/service.c          | 58 ++++++++++++++++++++++++++-----
 src/site/xdoc/procrun.xml                 |  2 +-
 6 files changed, 89 insertions(+), 22 deletions(-)

diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 19d0720..40c11e1 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -38,7 +38,7 @@
     <title>Apache Commons Daemon Release Notes</title>
   </properties>
   <body>
-    <release version="1.1.1" date="TBD" description="Bug fix release">
+    <release version="1.1.1" date="TBD" description="Feature and bug fix release">
       <action type="fix" dev="markt" due-to="mturk" >
         Procrun. Add to OPT_LFLAGS rather than overwrite OPT_LFLAGS when setting
         /OPT:REF in the make file for Windows.
@@ -122,6 +122,10 @@
         JNI to create the JVM as a workaround for startup error messages not
         being visible on stdout or stderr.
       </action>
+      <action issue="DAEMON-303" type="add" dev="markt">
+        Procrun. Add an option to configure the service to use the 'Automatic
+        (Delayed Start)' startup mode.
+      </action>
     </release>
     <release version="1.1.0" date="2017-11-15" description="Feature and bug fix release">
       <action issue="DAEMON-368" type="add" dev="ggregory">
diff --git a/src/native/windows/apps/prunmgr/prunmgr.c b/src/native/windows/apps/prunmgr/prunmgr.c
index 0b520c6..afae8c7 100644
--- a/src/native/windows/apps/prunmgr/prunmgr.c
+++ b/src/native/windows/apps/prunmgr/prunmgr.c
@@ -51,6 +51,7 @@ LPAPXGUISTORE _gui_store  = NULL;
 #define LOGL_INFO           L"Info"
 #define LOGL_WARN           L"Warn"
 
+#define START_DELAYED        L"Automatic (Delayed Start)"
 #define START_AUTO           L"Automatic"
 #define START_MANUAL         L"Manual"
 #define START_DISABLED       L"Disabled"
@@ -298,6 +299,8 @@ BOOL __generalPropertySave(HWND hDlg)
     WCHAR szN[SIZ_RESLEN];
     WCHAR szD[SIZ_DESLEN];
     DWORD dwStartType = SERVICE_NO_CHANGE;
+    BOOL  bDelayedStart = FALSE;
+
     int i;
 
     if (!(TST_BIT_FLAG(_propertyChanged, 1)))
@@ -309,14 +312,18 @@ BOOL __generalPropertySave(HWND hDlg)
     GetDlgItemTextW(hDlg, IDC_PPSGDISP, szN, SIZ_RESMAX);
     GetDlgItemTextW(hDlg, IDC_PPSGDESC, szD, SIZ_DESMAX);
     i = ComboBox_GetCurSel(GetDlgItem(hDlg, IDC_PPSGCMBST));
-    if (i == 0)
+    if (i == 0) {
         dwStartType = SERVICE_AUTO_START;
+        bDelayedStart = TRUE;
+    }
     else if (i == 1)
-        dwStartType = SERVICE_DEMAND_START;
+            dwStartType = SERVICE_AUTO_START;
     else if (i == 2)
+        dwStartType = SERVICE_DEMAND_START;
+    else if (i == 3)
         dwStartType = SERVICE_DISABLED;
     apxServiceSetNames(hService, NULL, szN, szD, NULL, NULL);
-    apxServiceSetOptions(hService, SERVICE_NO_CHANGE, dwStartType, SERVICE_NO_CHANGE);
+    apxServiceSetOptions(hService, SERVICE_NO_CHANGE, dwStartType, bDelayedStart, SERVICE_NO_CHANGE);
 
     if (!(TST_BIT_FLAG(_propertyChanged, 2)))
         PostMessage(_gui_store->hMainWnd, WM_COMMAND, MAKEWPARAM(IDMS_REFRESH, 0), 0);
@@ -355,12 +362,12 @@ BOOL __generalLogonSave(HWND hDlg)
         if (IsDlgButtonChecked(hDlg, IDC_PPSLID) == BST_CHECKED) {
             apxServiceSetOptions(hService,
                 _currentEntry->stServiceStatus.dwServiceType | SERVICE_INTERACTIVE_PROCESS,
-                SERVICE_NO_CHANGE, SERVICE_NO_CHANGE);
+                SERVICE_NO_CHANGE, FALSE, SERVICE_NO_CHANGE);
         }
         else {
             apxServiceSetOptions(hService,
                 _currentEntry->stServiceStatus.dwServiceType & ~SERVICE_INTERACTIVE_PROCESS,
-                SERVICE_NO_CHANGE, SERVICE_NO_CHANGE);
+                SERVICE_NO_CHANGE, FALSE, SERVICE_NO_CHANGE);
         }
     } else {
         if (szP[0] != L' ' &&  szC[0] != L' ' && !lstrcmpW(szP, szC)) {
@@ -607,15 +614,22 @@ LRESULT CALLBACK __generalProperty(HWND hDlg,
                 SendMessage(GetDlgItem(hDlg, IDC_PPSGDISP), EM_LIMITTEXT, SIZ_RESMAX, 0);
                 SendMessage(GetDlgItem(hDlg, IDC_PPSGDESC), EM_LIMITTEXT, SIZ_DESMAX, 0);
 
+                ComboBox_AddStringW(GetDlgItem(hDlg, IDC_PPSGCMBST), START_DELAYED);
                 ComboBox_AddStringW(GetDlgItem(hDlg, IDC_PPSGCMBST), START_AUTO);
                 ComboBox_AddStringW(GetDlgItem(hDlg, IDC_PPSGCMBST), START_MANUAL);
                 ComboBox_AddStringW(GetDlgItem(hDlg, IDC_PPSGCMBST), START_DISABLED);
-                if (_currentEntry->lpConfig->dwStartType == SERVICE_AUTO_START)
-                    ComboBox_SetCurSel(GetDlgItem(hDlg, IDC_PPSGCMBST), 0);
+                if (_currentEntry->lpConfig->dwStartType == SERVICE_AUTO_START) {
+                	if (_currentEntry->bDelayedStart) {
+                		ComboBox_SetCurSel(GetDlgItem(hDlg, IDC_PPSGCMBST), 0);
+                	}
+                	else {
+                		ComboBox_SetCurSel(GetDlgItem(hDlg, IDC_PPSGCMBST), 1);
+                	}
+                }
                 else if (_currentEntry->lpConfig->dwStartType == SERVICE_DEMAND_START)
-                    ComboBox_SetCurSel(GetDlgItem(hDlg, IDC_PPSGCMBST), 1);
-                else if (_currentEntry->lpConfig->dwStartType == SERVICE_DISABLED)
                     ComboBox_SetCurSel(GetDlgItem(hDlg, IDC_PPSGCMBST), 2);
+                else if (_currentEntry->lpConfig->dwStartType == SERVICE_DISABLED)
+                    ComboBox_SetCurSel(GetDlgItem(hDlg, IDC_PPSGCMBST), 3);
 
                 SetDlgItemTextW(hDlg, IDC_PPSGNAME, _currentEntry->szServiceName);
                 SetDlgItemTextW(hDlg, IDC_PPSGDISP, _currentEntry->lpConfig->lpDisplayName);
diff --git a/src/native/windows/apps/prunsrv/prunsrv.c b/src/native/windows/apps/prunsrv/prunsrv.c
index dab90e5..cf1ef48 100644
--- a/src/native/windows/apps/prunsrv/prunsrv.c
+++ b/src/native/windows/apps/prunsrv/prunsrv.c
@@ -64,6 +64,7 @@ static LPCWSTR  PRSRV_JAVA        = L"java";
 static LPCWSTR  PRSRV_JVM         = L"jvm";
 static LPCWSTR  PRSRV_JDK         = L"jdk";
 static LPCWSTR  PRSRV_JRE         = L"jre";
+static LPCWSTR  PRSRV_DELAYED     = L"delayed";
 static LPCWSTR  PRSRV_MANUAL      = L"manual";
 static LPCWSTR  PRSRV_JBIN        = L"\\bin\\java.exe";
 static LPCWSTR  PRSRV_PBIN        = L"\\bin";
@@ -834,6 +835,7 @@ static BOOL docmdUpdateService(LPAPXCMDLINE lpCmdline)
     }
     else {
         DWORD dwStart = SERVICE_NO_CHANGE;
+        BOOL  bDelayedStart = FALSE;
         DWORD dwType  = SERVICE_NO_CHANGE;
         LPCWSTR su = NULL;
         LPCWSTR sp = NULL;
@@ -855,7 +857,11 @@ static BOOL docmdUpdateService(LPAPXCMDLINE lpCmdline)
                                        sp));
         /* Update the --Startup mode */
         if (ST_STARTUP & APXCMDOPT_FOUND) {
-            if (!lstrcmpiW(SO_STARTUP, PRSRV_AUTO))
+            if (!lstrcmpiW(SO_STARTUP, PRSRV_DELAYED)) {
+                dwStart = SERVICE_AUTO_START;
+                bDelayedStart = TRUE;
+            }
+            else if (!lstrcmpiW(SO_STARTUP, PRSRV_AUTO))
                 dwStart = SERVICE_AUTO_START;
             else if (!lstrcmpiW(SO_STARTUP, PRSRV_MANUAL))
                 dwStart = SERVICE_DEMAND_START;
@@ -867,6 +873,7 @@ static BOOL docmdUpdateService(LPAPXCMDLINE lpCmdline)
         rv = (rv && apxServiceSetOptions(hService,
                                          dwType,
                                          dwStart,
+										 bDelayedStart,
                                          SERVICE_NO_CHANGE));
 
         apxLogWrite(APXLOG_MARK_INFO "Service '%S' updated",
diff --git a/src/native/windows/include/service.h b/src/native/windows/include/service.h
index faebef4..8da60f4 100644
--- a/src/native/windows/include/service.h
+++ b/src/native/windows/include/service.h
@@ -24,6 +24,7 @@ typedef struct APXSERVENTRY {
     WCHAR   szObjectName[SIZ_RESLEN];
     WCHAR   szServiceDescription[SIZ_DESLEN];
     LPQUERY_SERVICE_CONFIGW lpConfig;
+    BOOL					bDelayedStart;
     SERVICE_STATUS          stServiceStatus;
     SERVICE_STATUS_PROCESS  stStatusProcess;
 
@@ -41,7 +42,8 @@ BOOL        apxServiceSetNames(APXHANDLE hService, LPCWSTR szImagePath,
                                LPCWSTR szUsername, LPCWSTR szPassword);
 
 BOOL        apxServiceSetOptions(APXHANDLE hService, DWORD dwServiceType,
-                                 DWORD dwStartType, DWORD dwErrorControl);
+								 DWORD dwStartType, BOOL bDelayedStart,
+								 DWORD dwErrorControl);
 
 BOOL        apxServiceControl(APXHANDLE hService, DWORD dwControl, UINT uMsg,
                               LPAPXFNCALLBACK fnControlCallback,
diff --git a/src/native/windows/src/service.c b/src/native/windows/src/service.c
index 1fcc1c3..6317d58 100644
--- a/src/native/windows/src/service.c
+++ b/src/native/windows/src/service.c
@@ -107,6 +107,7 @@ apxServiceOpen(APXHANDLE hService, LPCWSTR szServiceName, DWORD dwOptions)
 {
     LPAPXSERVICE lpService;
     DWORD dwNeeded;
+    LPSERVICE_DELAYED_AUTO_START_INFO lpDelayedInfo;
 
     if (hService->dwType != APXHANDLE_TYPE_SERVICE)
         return FALSE;
@@ -157,11 +158,36 @@ apxServiceOpen(APXHANDLE hService, LPCWSTR szServiceName, DWORD dwOptions)
             apxLogWrite(APXLOG_MARK_SYSERR);
         }
     }
-    lpService->stServiceEntry.lpConfig =  (LPQUERY_SERVICE_CONFIGW)apxPoolAlloc(hService->hPool,
-                                                                                dwNeeded);
-    return QueryServiceConfigW(lpService->hService,
-                               lpService->stServiceEntry.lpConfig,
-                               dwNeeded, &dwNeeded);
+    lpService->stServiceEntry.lpConfig = (LPQUERY_SERVICE_CONFIGW)apxPoolAlloc(hService->hPool,
+                                                                               dwNeeded);
+    if (!QueryServiceConfigW(lpService->hService,
+                             lpService->stServiceEntry.lpConfig,
+                             dwNeeded, &dwNeeded)) {
+    	return FALSE;
+    }
+
+    if (!QueryServiceConfig2W(lpService->hService, SERVICE_CONFIG_DELAYED_AUTO_START_INFO,
+                              NULL, 0, &dwNeeded)) {
+        if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
+            // This is expected. The call is expected to fail with the required
+            // buffer size set in dwNeeded.
+            // Clear the last error to prevent it being logged if a genuine
+            // error occurs
+            SetLastError(ERROR_SUCCESS);
+        } else {
+            apxLogWrite(APXLOG_MARK_SYSERR);
+        }
+    }
+    lpDelayedInfo = (LPSERVICE_DELAYED_AUTO_START_INFO) apxPoolAlloc(hService->hPool, dwNeeded);
+
+    if (!QueryServiceConfig2W(lpService->hService, SERVICE_CONFIG_DELAYED_AUTO_START_INFO,
+                              (LPBYTE) lpDelayedInfo, dwNeeded, &dwNeeded)) {
+    	return FALSE;
+    }
+
+    lpService->stServiceEntry.bDelayedStart = lpDelayedInfo->fDelayedAutostart;
+    apxFree(lpDelayedInfo);
+    return TRUE;
 }
 
 LPAPXSERVENTRY
@@ -240,9 +266,11 @@ BOOL
 apxServiceSetOptions(APXHANDLE hService,
                      DWORD dwServiceType,
                      DWORD dwStartType,
+					 BOOL bDelayedStart,
                      DWORD dwErrorControl)
 {
     LPAPXSERVICE lpService;
+    SERVICE_DELAYED_AUTO_START_INFO sDelayedInfo;
 
     if (hService->dwType != APXHANDLE_TYPE_SERVICE)
         return FALSE;
@@ -254,10 +282,22 @@ apxServiceSetOptions(APXHANDLE hService,
     /* Check if the ServixeOpen has been called */
     if (IS_INVALID_HANDLE(lpService->hService))
         return FALSE;
-    return ChangeServiceConfig(lpService->hService, dwServiceType,
-                               dwStartType, dwErrorControl,
-                               NULL, NULL, NULL, NULL, NULL,
-                               NULL, NULL);
+
+    if (!ChangeServiceConfig(lpService->hService, dwServiceType,
+                                   dwStartType, dwErrorControl,
+                                   NULL, NULL, NULL, NULL, NULL,
+                                   NULL, NULL)) {
+    	return FALSE;
+    }
+
+    if (dwStartType == SERVICE_AUTO_START) {
+    	sDelayedInfo.fDelayedAutostart = bDelayedStart;
+    	return ChangeServiceConfig2A(lpService->hService,
+                                     SERVICE_CONFIG_DELAYED_AUTO_START_INFO,
+                                     &sDelayedInfo);
+    }
+
+    return TRUE;
 }
 
 static BOOL
diff --git a/src/site/xdoc/procrun.xml b/src/site/xdoc/procrun.xml
index 5838b24..9a49b81 100644
--- a/src/site/xdoc/procrun.xml
+++ b/src/site/xdoc/procrun.xml
@@ -312,7 +312,7 @@ will add the new value(s) to any existing value(s).
     <tr>
     <td>--Startup</td>
     <td>manual</td>
-    <td>Service startup mode can be either <b>auto</b> or <b>manual</b></td>
+    <td>Service startup mode can be either <b>delayed</b>, <b>auto</b> or <b>manual</b></td>
     </tr>
     <tr>
     <td>--Type</td>