diff options
author | schmidt <douglascraigschmidt@users.noreply.github.com> | 2000-01-18 04:16:59 +0000 |
---|---|---|
committer | schmidt <douglascraigschmidt@users.noreply.github.com> | 2000-01-18 04:16:59 +0000 |
commit | d4de8a9e6000f13de74c9050455bd38a77fffdbe (patch) | |
tree | 9d67308398a783953b71533e9cc07f60671a1239 | |
parent | f0b6139ba32b4246dd464778084114cb719db4fc (diff) | |
download | ATCD-d4de8a9e6000f13de74c9050455bd38a77fffdbe.tar.gz |
ChangeLogTag:Mon Jan 17 18:03:17 2000 Douglas C. Schmidt <schmidt@tango.cs.wustl.edu>
-rw-r--r-- | ChangeLog | 66 | ||||
-rw-r--r-- | ChangeLogs/ChangeLog-02a | 66 | ||||
-rw-r--r-- | ChangeLogs/ChangeLog-03a | 66 | ||||
-rw-r--r-- | THANKS | 5 | ||||
-rw-r--r-- | ace/NT_Service.cpp | 371 | ||||
-rw-r--r-- | ace/NT_Service.h | 254 | ||||
-rw-r--r-- | ace/Process_Manager.cpp | 11 | ||||
-rw-r--r-- | ace/Task.h | 2 | ||||
-rw-r--r-- | ace/Task_T.h | 2 |
9 files changed, 519 insertions, 324 deletions
diff --git a/ChangeLog b/ChangeLog index db870295d79..beb8c37c1d0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,71 @@ Mon Jan 17 18:03:17 2000 Douglas C. Schmidt <schmidt@tango.cs.wustl.edu> + * ace/Process_Manager.cpp: Under WIN32, the ACE_Process_Manager + registered itself as an event handler with ACE_Reactor, but did + not properly unregister itself when it closed. For error to be + noticed, you must instantiate ACE_Process_Manager with an + ACE_Reactor. ACE_Process_Manager should *not* be run as a + singleton. It must be instantiated such that it will be + destroyed *before* the ACE_Reactor is destroyed. + + When you call ACE_Process_Manager::spawn, the newly created + process is added to the ACE_Process_Manager's process table and + (under WIN32) the ACE_Process_Manager is registered as an event + handler for the new process (ace/Process_Manager.cpp, line 523) + using this call: + + r->register_handler (this, proc->gethandle ()); + + This will happen for every process spawned. Thus, + ACE_Process_Manager will potentially be associated with more + than one WIN32 process handle. + + When the ACE_Process_Manager was destroyed, the dtor calls + ACE_Process_Manager::close which (for WIN32) attempts to remove + ACE_Process_Manager as an Event_Handler from the ACE_Reactor + using the following code (ace/Process_Manager.cpp, line 256) + + this->reactor ()->remove_handler (this, 0); + + This version of ACE_Reactor::remove_handler is: + + int ACE_Reactor::remove_handler + ( + ACE_Event_Handler *event_handler, + ACE_Reactor_Mask mask + ); + + It calls event_handler->get_handle() to obtain the handle to + which 'event_handler' is associated. The problem is that + ACE_Process_Manager::get_handle returns ACE_INVALID_HANDLE, so + the ACE_Reactor never properly unregistered the + ACE_Process_Manager. This is now fixed and should work correctly + on Win32 and other platforms. + + Thanks to Greg Gallant <gcg@intercap.com> for tracking all this + down and providing the fix. + + * ace/Process_Manager.cpp (open): Wrapped the setpgid() call with a + #if !defined (ACE_LACKS_SETPGID) to remove spurious run-time + warnings on platforms that don't support setpgid(). Thanks to + Craig Perras <cperras@watchguard.com> for reporting this. + + * ace/NT_Service: Reformatted this head to conform to the ACE + programming guidelines. Also, replaced + + #if defined (ACE_HAS_WINNT4) && ACE_HAS_WINNT4 != 0) + + with + + #if defined (ACE_WIN32) + + This change allows a single dll to be built that supports both + NT and Win9x. The app can use GetVersionEx() to check whether + the platform is NT or not dynamically, or it can just call the + various service functions, which will return a function not + supported error. Thanks to Craig Perras + <cperras@watchguard.com> for reporting this. + * tests/Thread_Pool_Test.cpp: Enhanced this test to illustrate how to shut down Tasks using either the "empty message" strategy or the "queue deactivation" strategy. diff --git a/ChangeLogs/ChangeLog-02a b/ChangeLogs/ChangeLog-02a index db870295d79..beb8c37c1d0 100644 --- a/ChangeLogs/ChangeLog-02a +++ b/ChangeLogs/ChangeLog-02a @@ -1,5 +1,71 @@ Mon Jan 17 18:03:17 2000 Douglas C. Schmidt <schmidt@tango.cs.wustl.edu> + * ace/Process_Manager.cpp: Under WIN32, the ACE_Process_Manager + registered itself as an event handler with ACE_Reactor, but did + not properly unregister itself when it closed. For error to be + noticed, you must instantiate ACE_Process_Manager with an + ACE_Reactor. ACE_Process_Manager should *not* be run as a + singleton. It must be instantiated such that it will be + destroyed *before* the ACE_Reactor is destroyed. + + When you call ACE_Process_Manager::spawn, the newly created + process is added to the ACE_Process_Manager's process table and + (under WIN32) the ACE_Process_Manager is registered as an event + handler for the new process (ace/Process_Manager.cpp, line 523) + using this call: + + r->register_handler (this, proc->gethandle ()); + + This will happen for every process spawned. Thus, + ACE_Process_Manager will potentially be associated with more + than one WIN32 process handle. + + When the ACE_Process_Manager was destroyed, the dtor calls + ACE_Process_Manager::close which (for WIN32) attempts to remove + ACE_Process_Manager as an Event_Handler from the ACE_Reactor + using the following code (ace/Process_Manager.cpp, line 256) + + this->reactor ()->remove_handler (this, 0); + + This version of ACE_Reactor::remove_handler is: + + int ACE_Reactor::remove_handler + ( + ACE_Event_Handler *event_handler, + ACE_Reactor_Mask mask + ); + + It calls event_handler->get_handle() to obtain the handle to + which 'event_handler' is associated. The problem is that + ACE_Process_Manager::get_handle returns ACE_INVALID_HANDLE, so + the ACE_Reactor never properly unregistered the + ACE_Process_Manager. This is now fixed and should work correctly + on Win32 and other platforms. + + Thanks to Greg Gallant <gcg@intercap.com> for tracking all this + down and providing the fix. + + * ace/Process_Manager.cpp (open): Wrapped the setpgid() call with a + #if !defined (ACE_LACKS_SETPGID) to remove spurious run-time + warnings on platforms that don't support setpgid(). Thanks to + Craig Perras <cperras@watchguard.com> for reporting this. + + * ace/NT_Service: Reformatted this head to conform to the ACE + programming guidelines. Also, replaced + + #if defined (ACE_HAS_WINNT4) && ACE_HAS_WINNT4 != 0) + + with + + #if defined (ACE_WIN32) + + This change allows a single dll to be built that supports both + NT and Win9x. The app can use GetVersionEx() to check whether + the platform is NT or not dynamically, or it can just call the + various service functions, which will return a function not + supported error. Thanks to Craig Perras + <cperras@watchguard.com> for reporting this. + * tests/Thread_Pool_Test.cpp: Enhanced this test to illustrate how to shut down Tasks using either the "empty message" strategy or the "queue deactivation" strategy. diff --git a/ChangeLogs/ChangeLog-03a b/ChangeLogs/ChangeLog-03a index db870295d79..beb8c37c1d0 100644 --- a/ChangeLogs/ChangeLog-03a +++ b/ChangeLogs/ChangeLog-03a @@ -1,5 +1,71 @@ Mon Jan 17 18:03:17 2000 Douglas C. Schmidt <schmidt@tango.cs.wustl.edu> + * ace/Process_Manager.cpp: Under WIN32, the ACE_Process_Manager + registered itself as an event handler with ACE_Reactor, but did + not properly unregister itself when it closed. For error to be + noticed, you must instantiate ACE_Process_Manager with an + ACE_Reactor. ACE_Process_Manager should *not* be run as a + singleton. It must be instantiated such that it will be + destroyed *before* the ACE_Reactor is destroyed. + + When you call ACE_Process_Manager::spawn, the newly created + process is added to the ACE_Process_Manager's process table and + (under WIN32) the ACE_Process_Manager is registered as an event + handler for the new process (ace/Process_Manager.cpp, line 523) + using this call: + + r->register_handler (this, proc->gethandle ()); + + This will happen for every process spawned. Thus, + ACE_Process_Manager will potentially be associated with more + than one WIN32 process handle. + + When the ACE_Process_Manager was destroyed, the dtor calls + ACE_Process_Manager::close which (for WIN32) attempts to remove + ACE_Process_Manager as an Event_Handler from the ACE_Reactor + using the following code (ace/Process_Manager.cpp, line 256) + + this->reactor ()->remove_handler (this, 0); + + This version of ACE_Reactor::remove_handler is: + + int ACE_Reactor::remove_handler + ( + ACE_Event_Handler *event_handler, + ACE_Reactor_Mask mask + ); + + It calls event_handler->get_handle() to obtain the handle to + which 'event_handler' is associated. The problem is that + ACE_Process_Manager::get_handle returns ACE_INVALID_HANDLE, so + the ACE_Reactor never properly unregistered the + ACE_Process_Manager. This is now fixed and should work correctly + on Win32 and other platforms. + + Thanks to Greg Gallant <gcg@intercap.com> for tracking all this + down and providing the fix. + + * ace/Process_Manager.cpp (open): Wrapped the setpgid() call with a + #if !defined (ACE_LACKS_SETPGID) to remove spurious run-time + warnings on platforms that don't support setpgid(). Thanks to + Craig Perras <cperras@watchguard.com> for reporting this. + + * ace/NT_Service: Reformatted this head to conform to the ACE + programming guidelines. Also, replaced + + #if defined (ACE_HAS_WINNT4) && ACE_HAS_WINNT4 != 0) + + with + + #if defined (ACE_WIN32) + + This change allows a single dll to be built that supports both + NT and Win9x. The app can use GetVersionEx() to check whether + the platform is NT or not dynamically, or it can just call the + various service functions, which will return a function not + supported error. Thanks to Craig Perras + <cperras@watchguard.com> for reporting this. + * tests/Thread_Pool_Test.cpp: Enhanced this test to illustrate how to shut down Tasks using either the "empty message" strategy or the "queue deactivation" strategy. @@ -504,7 +504,7 @@ Keith Brown <kalbrown@ix.netcom.com> Barry Hoggard <hoggard@cfx.com> Peter J. Mason <peterm@fl.net.au> Jerry D. De Master <jdemaste@ipdinc.com> -Greg Gallant <greg.gallant@jhuapl.edu> +Greg Gallant <gcg@intercap.com> wym <wym@dekang.com> Karel Zuiderveld <kzuiderveld@vitalimages.com> Mike Goldman <whig@by.net> @@ -869,6 +869,8 @@ Hugh Arnold <harnold@itginc.com> Hessel Idzenga <idzenga@lucent.com> Mark C. Barnes <marcus@muse3d.com> Suresh Kannan <kannan@uav.ae.gatech.edu> +Alex Scholte <Alex.Scholte@getronics.com> +Greg Jansen <plaidriver@msn.com> I would particularly like to thank Paul Stephenson, who worked with me at Ericsson. Paul devised the recursive Makefile scheme that @@ -889,3 +891,4 @@ improvements, suggestions, and or comments, I'd like to hear about it. Douglas C. Schmidt schmidt@cs.wustl.edu + diff --git a/ace/NT_Service.cpp b/ace/NT_Service.cpp index 09e77617cc1..fbc74d5a94b 100644 --- a/ace/NT_Service.cpp +++ b/ace/NT_Service.cpp @@ -3,7 +3,7 @@ // NT_Service.cpp #include "ace/inc_user_config.h" -#if defined (ACE_HAS_WINNT4) && ACE_HAS_WINNT4 != 0 +#if defined (ACE_WIN32) #define ACE_BUILD_DLL #include "ace/NT_Service.h" @@ -15,62 +15,64 @@ ACE_ALLOC_HOOK_DEFINE(ACE_NT_Service) - // ACE_NT_Service destructor. ACE_NT_Service::~ACE_NT_Service (void) { if (svc_sc_handle_ != 0) - { - CloseServiceHandle(svc_sc_handle_); - svc_sc_handle_ = 0; - } - delete[] desc_; - delete[] name_; + { + CloseServiceHandle (svc_sc_handle_); + svc_sc_handle_ = 0; + } + delete [] desc_; + delete [] name_; } - -// This default implementation of ACE_NT_Service::open sets the service's -// status to START_PENDING with the estimated time until STARTED set to the -// value given when this object was constructed. Then the svc function is -// called, which implements the guts of the service. Note that this function -// is running in a thread created by the OS, not by ACE_Thread_Manager. -// The thread manager does not know anything about this thread. The service -// can, however, use ACE_Thread_Manager to start more threads if desired. -// When the svc function returns, the service status is set to STOPPED, and -// exit codes set based on errno/GetLastError if the svc function returns -1. +// This default implementation of ACE_NT_Service::open sets the +// service's status to START_PENDING with the estimated time until +// STARTED set to the value given when this object was constructed. +// Then the svc function is called, which implements the guts of the +// service. Note that this function is running in a thread created by +// the OS, not by ACE_Thread_Manager. The thread manager does not +// know anything about this thread. The service can, however, use +// ACE_Thread_Manager to start more threads if desired. When the svc +// function returns, the service status is set to STOPPED, and exit +// codes set based on errno/GetLastError if the svc function returns +// -1. // // The svc function is expected to set the service status to SERVICE_RUNNING // after it initializes. // -// The handle_control function will be called for each time there is a request -// for the service. It is up to that function and svc to cooperate to both -// respond appropriately to the request (by at least updating the service's -// status) and to fulfill the request. +// The handle_control function will be called for each time there is a +// request for the service. It is up to that function and svc to +// cooperate to both respond appropriately to the request (by at least +// updating the service's status) and to fulfill the request. int ACE_NT_Service::open (void *args) { + report_status (SERVICE_START_PENDING, 0); -int svc_return; - - report_status(SERVICE_START_PENDING, 0); - - if ((svc_return = this->svc()) == 0) { - this->svc_status_.dwWin32ExitCode = NO_ERROR; - this->svc_status_.dwServiceSpecificExitCode = 0; - } - else { - if (errno == 0) { - this->svc_status_.dwWin32ExitCode = GetLastError(); + int svc_return = this->svc (); + if (svc_return == 0) + { + this->svc_status_.dwWin32ExitCode = NO_ERROR; + this->svc_status_.dwServiceSpecificExitCode = 0; } - else { - this->svc_status_.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR; - this->svc_status_.dwServiceSpecificExitCode = errno; + else + { + if (errno == 0) + { + this->svc_status_.dwWin32ExitCode = GetLastError (); + } + else + { + this->svc_status_.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR; + this->svc_status_.dwServiceSpecificExitCode = errno; + } } - } - report_status(SERVICE_STOPPED, 0); + report_status (SERVICE_STOPPED, 0); return svc_return; @@ -79,31 +81,27 @@ int svc_return; void ACE_NT_Service::handle_control (DWORD control_code) { - - switch(control_code) { - case SERVICE_CONTROL_SHUTDOWN: - case SERVICE_CONTROL_STOP: - stop_requested(control_code); - break; - - case SERVICE_CONTROL_PAUSE: - pause_requested(control_code); - break; - - case SERVICE_CONTROL_CONTINUE: - continue_requested(control_code); - break; - - case SERVICE_CONTROL_INTERROGATE: - interrogate_requested(control_code); - break; - } - - return; - + switch(control_code) + { + case SERVICE_CONTROL_SHUTDOWN: + case SERVICE_CONTROL_STOP: + stop_requested (control_code); + break; + + case SERVICE_CONTROL_PAUSE: + pause_requested (control_code); + break; + + case SERVICE_CONTROL_CONTINUE: + continue_requested (control_code); + break; + + case SERVICE_CONTROL_INTERROGATE: + interrogate_requested (control_code); + break; + } } - void ACE_NT_Service::stop_requested (DWORD) { @@ -111,7 +109,6 @@ ACE_NT_Service::stop_requested (DWORD) /* how to cancel? */ } - void ACE_NT_Service::pause_requested (DWORD) { @@ -120,7 +117,6 @@ ACE_NT_Service::pause_requested (DWORD) report_status (SERVICE_PAUSED); } - void ACE_NT_Service::continue_requested (DWORD) { @@ -129,32 +125,25 @@ ACE_NT_Service::continue_requested (DWORD) report_status (SERVICE_RUNNING); } - void ACE_NT_Service::interrogate_requested (DWORD) { this->report_status (0); } - void ACE_NT_Service::name (LPCTSTR name, LPCTSTR desc) { - - delete[] desc_; - delete[] name_; + delete [] desc_; + delete [] name_; if (desc == 0) desc = name; - name_ = ACE::strnew(name); - desc_ = ACE::strnew(desc); - - return; - + name_ = ACE::strnew (name); + desc_ = ACE::strnew (desc); } - int ACE_NT_Service::insert (DWORD start_type, DWORD error_control, @@ -165,33 +154,32 @@ ACE_NT_Service::insert (DWORD start_type, LPCTSTR account_name, LPCTSTR password) { - -TCHAR this_exe[MAXPATHLEN]; + TCHAR this_exe[MAXPATHLEN]; if (exe_path == 0) { - if (GetModuleFileName(0, this_exe, sizeof(this_exe)) == 0) + if (GetModuleFileName (0, this_exe, sizeof this_exe) == 0) return -1; exe_path = this_exe; } - SC_HANDLE sc_mgr = OpenSCManager(0, 0, SC_MANAGER_ALL_ACCESS); + SC_HANDLE sc_mgr = OpenSCManager (0, 0, SC_MANAGER_ALL_ACCESS); if (sc_mgr == 0) return -1; - SC_HANDLE sh = CreateService(sc_mgr, - this->name(), - this->desc(), - SERVICE_ALL_ACCESS, - svc_status_.dwServiceType, - start_type, - error_control, - exe_path, - group_name, - tag_id, - dependencies, - account_name, password); - CloseServiceHandle(sc_mgr); + SC_HANDLE sh = CreateService (sc_mgr, + this->name (), + this->desc (), + SERVICE_ALL_ACCESS, + svc_status_.dwServiceType, + start_type, + error_control, + exe_path, + group_name, + tag_id, + dependencies, + account_name, password); + CloseServiceHandle (sc_mgr); if (sh == 0) return -1; @@ -201,29 +189,25 @@ TCHAR this_exe[MAXPATHLEN]; } - int ACE_NT_Service::remove (void) { - - if (this->svc_sc_handle() == 0) + if (this->svc_sc_handle () == 0) return -1; - if (DeleteService(this->svc_sc_handle()) == 0 && - GetLastError() != ERROR_SERVICE_MARKED_FOR_DELETE) + if (DeleteService (this->svc_sc_handle()) == 0 + && GetLastError () != ERROR_SERVICE_MARKED_FOR_DELETE) return -1; return 0; - } - -// Sets the startup type for the service. Returns -1 on error, 0 on success. +// Sets the startup type for the service. Returns -1 on error, 0 on +// success. int ACE_NT_Service::startup (DWORD startup) { - - SC_HANDLE svc = this->svc_sc_handle(); + SC_HANDLE svc = this->svc_sc_handle (); if (svc == 0) return -1; @@ -239,28 +223,27 @@ ACE_NT_Service::startup (DWORD startup) 0); // No change to name return ok ? 0 : -1; - } - // Returns the current startup type. + DWORD ACE_NT_Service::startup (void) { - -// The query buffer will hold strings as well as the defined struct. The -// string pointers in the struct point to other areas in the passed memory -// area, so it has to be large enough to hold the struct plus all the strings. -char cfgbuff[1024]; -LPQUERY_SERVICE_CONFIG cfg; -DWORD cfgsize, needed_size; - - SC_HANDLE svc = this->svc_sc_handle(); + // The query buffer will hold strings as well as the defined struct. + // The string pointers in the struct point to other areas in the + // passed memory area, so it has to be large enough to hold the + // struct plus all the strings. + char cfgbuff[1024]; + LPQUERY_SERVICE_CONFIG cfg; + DWORD cfgsize, needed_size; + + SC_HANDLE svc = this->svc_sc_handle (); if (svc == 0) return -1; - cfgsize = sizeof(cfgbuff); - cfg = (LPQUERY_SERVICE_CONFIG)cfgbuff; + cfgsize = sizeof cfgbuff; + cfg = (LPQUERY_SERVICE_CONFIG) cfgbuff; BOOL ok = QueryServiceConfig (svc, cfg, cfgsize, &needed_size); if (ok) return cfg->dwStartType; @@ -268,18 +251,16 @@ DWORD cfgsize, needed_size; } - int ACE_NT_Service::start_svc (ACE_Time_Value *wait_time, DWORD *svc_state, DWORD argc, LPCTSTR *argv) { - - SC_HANDLE svc = this->svc_sc_handle(); + SC_HANDLE svc = this->svc_sc_handle (); if (svc == 0) return -1; - if (!StartService(svc, argc, argv)) + if (!StartService (svc, argc, argv)) return -1; wait_for_service_state (SERVICE_RUNNING, wait_time); @@ -287,124 +268,122 @@ ACE_NT_Service::start_svc (ACE_Time_Value *wait_time, *svc_state = this->svc_status_.dwCurrentState; return 0; - } - int -ACE_NT_Service::stop_svc (ACE_Time_Value *wait_time, DWORD *svc_state) +ACE_NT_Service::stop_svc (ACE_Time_Value *wait_time, + DWORD *svc_state) { - - SC_HANDLE svc = this->svc_sc_handle(); + SC_HANDLE svc = this->svc_sc_handle (); if (svc == 0) return -1; - if (!ControlService (svc, SERVICE_CONTROL_STOP, &this->svc_status_)) + if (!ControlService (svc, + SERVICE_CONTROL_STOP, + &this->svc_status_)) return -1; - wait_for_service_state (SERVICE_STOPPED, wait_time); + wait_for_service_state (SERVICE_STOPPED, + wait_time); if (svc_state != 0) *svc_state = this->svc_status_.dwCurrentState; return 0; - } - int -ACE_NT_Service::pause_svc (ACE_Time_Value *wait_time, DWORD *svc_state) +ACE_NT_Service::pause_svc (ACE_Time_Value *wait_time, + DWORD *svc_state) { - - SC_HANDLE svc = this->svc_sc_handle(); + SC_HANDLE svc = this->svc_sc_handle (); if (svc == 0) return -1; - if (!ControlService (svc, SERVICE_CONTROL_PAUSE, &this->svc_status_)) + if (!ControlService (svc, + SERVICE_CONTROL_PAUSE, + &this->svc_status_)) return -1; - wait_for_service_state (SERVICE_PAUSED, wait_time); + wait_for_service_state (SERVICE_PAUSED, + wait_time); if (svc_state != 0) *svc_state = this->svc_status_.dwCurrentState; return 0; - } - int -ACE_NT_Service::continue_svc (ACE_Time_Value *wait_time, DWORD *svc_state) +ACE_NT_Service::continue_svc (ACE_Time_Value *wait_time, + DWORD *svc_state) { - - SC_HANDLE svc = this->svc_sc_handle(); + SC_HANDLE svc = this->svc_sc_handle (); if (svc == 0) return -1; - if (!ControlService (svc, SERVICE_CONTROL_CONTINUE, &this->svc_status_)) + if (!ControlService (svc, + SERVICE_CONTROL_CONTINUE, + &this->svc_status_)) return -1; - wait_for_service_state (SERVICE_RUNNING, wait_time); + wait_for_service_state (SERVICE_RUNNING, + wait_time); if (svc_state != 0) *svc_state = this->svc_status_.dwCurrentState; return 0; - } - DWORD ACE_NT_Service::state (ACE_Time_Value *wait_hint) { + DWORD curr_state; -DWORD curr_state; - - if (this->state (&curr_state, wait_hint) == -1) + if (this->state (&curr_state, + wait_hint) == -1) return 0; return curr_state; - } - int -ACE_NT_Service::state (DWORD *pstate, ACE_Time_Value *wait_hint) +ACE_NT_Service::state (DWORD *pstate, + ACE_Time_Value *wait_hint) { - - SC_HANDLE svc = this->svc_sc_handle(); + SC_HANDLE svc = this->svc_sc_handle (); if (svc == 0) return -1; - if (QueryServiceStatus (svc, &this->svc_status_) == 0) + if (QueryServiceStatus (svc, + &this->svc_status_) == 0) return -1; if (wait_hint != 0) - { - wait_hint->msec(this->svc_status_.dwWaitHint); - } + wait_hint->msec (this->svc_status_.dwWaitHint); *pstate = this->svc_status_.dwCurrentState; return 0; - } - - // test_access // -// Open a new handle, ignoring any handle open in svc_sc_handle_. This -// function's results are returned without leaving the handle open. +// Open a new handle, ignoring any handle open in svc_sc_handle_. +// This function's results are returned without leaving the handle +// open. + int ACE_NT_Service::test_access (DWORD desired_access) { - int status = -1; // Guilty until proven innocent - SC_HANDLE sc_mgr = OpenSCManager(0, 0, GENERIC_READ); + SC_HANDLE sc_mgr = OpenSCManager (0, + 0, + GENERIC_READ); if (sc_mgr != 0) { - SC_HANDLE handle = OpenService(sc_mgr, - this->name(), - desired_access); - CloseServiceHandle(sc_mgr); + SC_HANDLE handle = OpenService (sc_mgr, + this->name (), + desired_access); + CloseServiceHandle (sc_mgr); if (handle != 0) { status = 0; @@ -413,34 +392,30 @@ ACE_NT_Service::test_access (DWORD desired_access) } return status; - } - - // report_status // -// Reports the current status. If new_status is not 0, it sets the +// Reports the current status. If new_status is not 0, it sets the // status to the new value before reporting. NOTE - this assumes that // no actual service status values have the value 0. This is true in -// WinNT 4. -// If the status is a 'pending' type, the supplied time hint is used -// unless it's 0, in which case the existing hint is used. The dwWaitHint -// is not updated by this function. The checkpoint is incremented -// by one after a pending report. -// +// WinNT 4. If the status is a 'pending' type, the supplied time hint +// is used unless it's 0, in which case the existing hint is used. +// The dwWaitHint is not updated by this function. The checkpoint is +// incremented by one after a pending report. + int -ACE_NT_Service::report_status (DWORD new_status, DWORD time_hint) +ACE_NT_Service::report_status (DWORD new_status, + DWORD time_hint) { - -int bump_checkpoint = 0, - retval = 0; -DWORD save_controls = 0; - + int bump_checkpoint = 0; + int retval = 0; + DWORD save_controls = 0; if (new_status != 0) this->svc_status_.dwCurrentState = new_status; - switch(this->svc_status_.dwCurrentState) { + switch (this->svc_status_.dwCurrentState) + { case SERVICE_START_PENDING: save_controls = this->svc_status_.dwControlsAccepted; this->svc_status_.dwControlsAccepted = 0; @@ -456,7 +431,8 @@ DWORD save_controls = 0; this->svc_status_.dwCheckPoint = 0; } - retval = SetServiceStatus(this->svc_handle_, &this->svc_status_) ? 0 : -1; + retval = SetServiceStatus (this->svc_handle_, + &this->svc_status_) ? 0 : -1; if (save_controls != 0) this->svc_status_.dwControlsAccepted = save_controls; @@ -465,43 +441,38 @@ DWORD save_controls = 0; ++this->svc_status_.dwCheckPoint; return retval; - } - SC_HANDLE ACE_NT_Service::svc_sc_handle (void) { - if (svc_sc_handle_ == 0) { - SC_HANDLE sc_mgr = OpenSCManager(0, 0, SC_MANAGER_ALL_ACCESS); + SC_HANDLE sc_mgr = OpenSCManager (0, + 0, + SC_MANAGER_ALL_ACCESS); if (sc_mgr != 0) { - svc_sc_handle_ = OpenService(sc_mgr, - this->name(), - SERVICE_ALL_ACCESS); - CloseServiceHandle(sc_mgr); + svc_sc_handle_ = OpenService (sc_mgr, + this->name (), + SERVICE_ALL_ACCESS); + CloseServiceHandle (sc_mgr); } } return svc_sc_handle_; - } - void ACE_NT_Service::wait_for_service_state (DWORD desired_state, ACE_Time_Value *wait_time) { + // Doing the right thing with these needs to be added. + ACE_UNUSED_ARG (desired_state); + ACE_UNUSED_ARG (wait_time); -// Doing the right thing with these needs to be added. -ACE_UNUSED_ARG(desired_state); -ACE_UNUSED_ARG(wait_time); - - QueryServiceStatus (this->svc_sc_handle_, &this->svc_status_); - return; - + QueryServiceStatus (this->svc_sc_handle_, + &this->svc_status_); } -#endif /* ACE_HAS_WINNT4 */ +#endif /* ACE_WIN32 */ diff --git a/ace/NT_Service.h b/ace/NT_Service.h index ed43e3668d8..198ca902cce 100644 --- a/ace/NT_Service.h +++ b/ace/NT_Service.h @@ -10,7 +10,7 @@ // NT_Service.h // // = AUTHOR -// Steve Huston +// Steve Huston <shuston@riverace.com> // // ============================================================================ @@ -23,62 +23,16 @@ # pragma once #endif /* ACE_LACKS_PRAGMA_ONCE */ -#if defined (ACE_HAS_WINNT4) && ACE_HAS_WINNT4 != 0 +#if defined (ACE_WIN32) #include "ace/Service_Object.h" #include "ace/Synch.h" #include "ace/Task.h" -// NT Services can be implemented using the framework defined by the -// ACE_NT_Service class, and the macros defined in this file. Some quick -// refresher notes on NT Services: -// - The main program defines an array of entries describing the services -// offered. The ACE_NT_SERVICE_ENTRY macro can help with this. -// - For each service, a separate ServiceMain and Handler function need to -// be defined. These are taken care of by the ACE_NT_SERVICE_DEFINE -// macro. -// - When the main program/thread calls StartServiceCtrlDispatcher, NT -// creates a thread for each service, and runs the ServiceMain function -// for the service in that new thread. When that thread exits, the service -// is gone. -// -// To use this facility, you could derive a class from ACE_Service_Object (if -// you want to start via ACE's service configurator), or use any other class -// to run when the image starts (assuming that NT runs the image). You must -// set up an NT SERVICE_TABLE_ENTRY array to define your service(s). You -// can use the ACE_NT_SERVICE_... macros defined below for this. -// A SERVICE_TABLE might look like this: -// ACE_NT_SERVICE_REFERENCE(Svc1); // If service is in another file -// SERVICE_TABLE_ENTRY myServices[] = { -// ACE_NT_SERVICE_ENTRY ("MyNeatService", Svc1), -// { 0, 0 } }; -// -// In the file where your service(s) are implemented, use the -// ACE_NT_SERVICE_DEFINE macro to set up the following: -// 1. A pointer to the service's implementation object (must be derived -// from ACE_NT_Service). -// 2. The service's Handler function (forwards all requests to the -// ACE_NT_Service-derived object's handle_control function). -// 3. The service's ServiceMain function. Creates a new instance of the -// ACE_NT_Service-derived class SVCCLASS, unless one has been created -// already. -// -// If you are using all the default constructor values, you -// can let the generated ServiceMain function create the object, else -// you need to create it by hand before calling StartServiceCtrlDispatcher. -// Set the pointer so ServiceMain won't create another one. -// Another reason you may want to do the object creation yourself is if you -// want to also implement suspend and resume functions (the ones inherited -// from ACE_Service_Object) to do something intelligent to the services which -// are running, like call their handle_control functions to request suspend -// and resume actions, similar to what NT would do if a Services control panel -// applet would do if the user clicks on Suspend. - - -// ACE_NT_SERVICE_START_TIMEOUT is an estimate of the number of milliseconds -// your service will take to start. Default is 5 seconds; you can pass -// a different value (or set one) when you create the ACE_NT_Service object -// for your service. +// ACE_NT_SERVICE_START_TIMEOUT is an estimate of the number of +// milliseconds your service will take to start. Default is 5 +// seconds; you can pass a different value (or set one) when you +// create the ACE_NT_Service object for your service. #if !defined ACE_NT_SERVICE_START_TIMEOUT #define ACE_NT_SERVICE_START_TIMEOUT 5000 #endif /* ACE_NT_SERVICE_TIMEOUT */ @@ -90,6 +44,56 @@ class ACE_Export ACE_NT_Service : public ACE_Task<ACE_MT_SYNCH> // an NT service. // // = DESCRIPTION + // NT Services can be implemented using the framework defined by + // the ACE_NT_Service class, and the macros defined in this file. + // Some quick refresher notes on NT Services: + + // - The main program defines an array of entries describing the + // services offered. The ACE_NT_SERVICE_ENTRY macro can help with + // this. + // - For each service, a separate ServiceMain and Handler function + // need to be defined. These are taken care of by the + // ACE_NT_SERVICE_DEFINE macro. + // - When the main program/thread calls + // StartServiceCtrlDispatcher, NT creates a thread for each + // service, and runs the ServiceMain function for the service in + // that new thread. When that thread exits, the service is gone. + // + // To use this facility, you could derive a class from + // ACE_Service_Object (if you want to start via ACE's service + // configurator), or use any other class to run when the image + // starts (assuming that NT runs the image). You must set up an + // NT SERVICE_TABLE_ENTRY array to define your service(s). You + // can use the ACE_NT_SERVICE_... macros defined below for this. + // + // A SERVICE_TABLE might look like this: + // ACE_NT_SERVICE_REFERENCE(Svc1); // If service is in another file + // SERVICE_TABLE_ENTRY myServices[] = { + // ACE_NT_SERVICE_ENTRY ("MyNeatService", Svc1), + // { 0, 0 } }; + // + // In the file where your service(s) are implemented, use the + // ACE_NT_SERVICE_DEFINE macro to set up the following: + // 1. A pointer to the service's implementation object (must be derived + // from ACE_NT_Service). + // 2. The service's Handler function (forwards all requests to the + // ACE_NT_Service-derived object's handle_control function). + // 3. The service's ServiceMain function. Creates a new instance + // of the ACE_NT_Service-derived class SVCCLASS, unless one has + // been created already. + // + // If you are using all the default constructor values, you can + // let the generated ServiceMain function create the object, else + // you need to create it by hand before calling + // StartServiceCtrlDispatcher. Set the pointer so ServiceMain + // won't create another one. Another reason you may want to do + // the object creation yourself is if you want to also implement + // suspend and resume functions (the ones inherited from + // ACE_Service_Object) to do something intelligent to the services + // which are running, like call their handle_control functions to + // request suspend and resume actions, similar to what NT would do + // if a Services control panel applet would do if the user clicks + // on Suspend. public: // = Initialization and termination methods. ACE_NT_Service (DWORD start_timeout = ACE_NT_SERVICE_START_TIMEOUT, @@ -177,51 +181,54 @@ public: // = Methods which control the service's execution. - // These methods to start/pause/resume/stop/check the service all have the - // following common behavior with respect to <wait_time> and return value. - // <wait_time> is a pointer to an ACE_Time_Value object. If not supplied - // (a zero pointer) the function will wait indefinitely for the action - // to be finalized (service reach running state, completely shut down, - // etc.) or get "stuck" before returning. If the time is supplied, it - // specifies how long to wait for the service to reach a steady state, - // and on return, it is updated to the service's last reported wait hint. - // So, if you want to control the waiting yourself (for example, you want - // to react to UI events during the wait) specify a <wait_time> of (0, 0) - // and use the updated time to know when to check the service's state - // again. - // NOTE!!!! The wait_time things don't work yet. The calls always - // check status once, and do not wait for it to change. + + // These methods to start/pause/resume/stop/check the service all + // have the following common behavior with respect to <wait_time> + // and return value. <wait_time> is a pointer to an ACE_Time_Value + // object. If not supplied (a zero pointer) the function will wait + // indefinitely for the action to be finalized (service reach + // running state, completely shut down, etc.) or get "stuck" before + // returning. If the time is supplied, it specifies how long to + // wait for the service to reach a steady state, and on return, it + // is updated to the service's last reported wait hint. So, if you + // want to control the waiting yourself (for example, you want to + // react to UI events during the wait) specify a <wait_time> of (0, + // 0) and use the updated time to know when to check the service's + // state again. NOTE!!!! The wait_time things don't work yet. The + // calls always check status once, and do not wait for it to change. // - // The return value from start_svc, stop_svc, pause_svc, continue_svc is - // 0 if the request to NT to effect the change was made successfully. The - // service may refuse to change, or not do what you wanted; so if you - // need to know, supply a <svc_state> pointer to receive the service's - // reported last state on return and check it to see if it's what you - // want. The functions only return -1 when the actual request to the - // service is refused - this would include privilege restrictions and - // if the service is not configured to receive the request (this is most - // likely to happen in the case of pause and continue). + // The return value from start_svc, stop_svc, pause_svc, + // continue_svc is 0 if the request to NT to effect the change was + // made successfully. The service may refuse to change, or not do + // what you wanted; so if you need to know, supply a <svc_state> + // pointer to receive the service's reported last state on return + // and check it to see if it's what you want. The functions only + // return -1 when the actual request to the service is refused - + // this would include privilege restrictions and if the service is + // not configured to receive the request (this is most likely to + // happen in the case of pause and continue). int start_svc (ACE_Time_Value *wait_time = 0, DWORD *svc_state = 0, DWORD argc = 0, LPCTSTR *argv = 0); - // Start the service (must have been inserted before). wait_time is the - // time to wait for the service to reach a steady state before returning. - // If it is 0, the function waits as long as it takes for the service to - // reach the 'running' state, or gets stuck in some other state, or exits. - // If <wait_time> is supplied, it is updated on return to hold the service's - // last reported wait hint. - // svc_state can be used to receive the state which the service settled in. - // If the value is 0, the service never ran. argc/argv are passed - // to the service's ServiceMain function when it starts. Returns 0 for - // success, -1 for error. + // Start the service (must have been inserted before). wait_time is + // the time to wait for the service to reach a steady state before + // returning. If it is 0, the function waits as long as it takes + // for the service to reach the 'running' state, or gets stuck in + // some other state, or exits. If <wait_time> is supplied, it is + // updated on return to hold the service's last reported wait hint. + // svc_state can be used to receive the state which the service + // settled in. If the value is 0, the service never ran. argc/argv + // are passed to the service's ServiceMain function when it starts. + // Returns 0 for success, -1 for error. int stop_svc (ACE_Time_Value *wait_time = 0, DWORD *svc_state = 0); - // Requests the service to stop. Will wait up to <wait_time> for the service - // to actually stop. If not specified, the function waits until the service - // either stops or gets stuck in some other state before it stops. - // If <svc_state> is specified, it receives the last reported state of the - // service. Returns 0 if the request was made successfully, -1 if not. + // Requests the service to stop. Will wait up to <wait_time> for + // the service to actually stop. If not specified, the function + // waits until the service either stops or gets stuck in some other + // state before it stops. If <svc_state> is specified, it receives + // the last reported state of the service. Returns 0 if the request + // was made successfully, -1 if not. int pause_svc (ACE_Time_Value *wait_time = 0, DWORD *svc_state = 0); // Pause the service. @@ -230,25 +237,25 @@ public: // Continue the service. DWORD state (ACE_Time_Value *wait_hint = 0); - // Get the current state for the service. If <wait_hint> is not 0, it - // receives the service's reported wait hint. - // Note that this function returns 0 on failure (not -1 as is usual in ACE). - // A zero return would (probably) only be returned if there is either no - // service with the given name in the SCM database, or the caller does not - // have sufficient rights to access the service state. The set of valid - // service state values are all greater than 0. + // Get the current state for the service. If <wait_hint> is not 0, + // it receives the service's reported wait hint. Note that this + // function returns 0 on failure (not -1 as is usual in ACE). A + // zero return would (probably) only be returned if there is either + // no service with the given name in the SCM database, or the caller + // does not have sufficient rights to access the service state. The + // set of valid service state values are all greater than 0. int state (DWORD *pstate, ACE_Time_Value *wait_hint = 0); // A version of <state> that returns -1 for failure, 0 for success. // The DWORD pointed to by pstate receives the state value. int test_access (DWORD desired_access = SERVICE_ALL_ACCESS); - // Test access to the object's service in the SCM. The service must already - // have been inserted in the SCM database. This function has no affect on - // the service itself. Returns 0 if the specified access is allowed, -1 - // otherwise (either the access is denied, or there is a problem with the - // service's definition - check ACE_OS::last_error to get the specific - // error indication. + // Test access to the object's service in the SCM. The service must + // already have been inserted in the SCM database. This function + // has no affect on the service itself. Returns 0 if the specified + // access is allowed, -1 otherwise (either the access is denied, or + // there is a problem with the service's definition - check + // ACE_OS::last_error to get the specific error indication. ACE_ALLOC_HOOK_DECLARE; // Declare the dynamic allocation hooks. @@ -257,19 +264,20 @@ protected: int report_status (DWORD new_status, DWORD time_hint = 0); SC_HANDLE svc_sc_handle (void); - // Return the svc_sc_handle_ member. If the member is null, - // it retrieves the handle from the Service Control Manager and caches it. + // Return the svc_sc_handle_ member. If the member is null, it + // retrieves the handle from the Service Control Manager and caches + // it. void wait_for_service_state (DWORD desired_state, ACE_Time_Value *wait_time); - // Waits for the service to reach <desired_state> or get (apparently) stuck - // before it reaches that state. Will wait at most <wait_time> to get to - // the desired state. If <wait_time> is 0, then the function keeps waiting - // until the desired state is reached or the service doesn't update its - // state any further. - // The svc_status_ class member is updated upon return. - // NOTE - the timeout doesn't currently work - it always acts like - // ACE_Time_Value::zero is passed - it checks the state once but doesn't - // wait after that. + // Waits for the service to reach <desired_state> or get + // (apparently) stuck before it reaches that state. Will wait at + // most <wait_time> to get to the desired state. If <wait_time> is + // 0, then the function keeps waiting until the desired state is + // reached or the service doesn't update its state any further. The + // svc_status_ class member is updated upon return. NOTE - the + // timeout doesn't currently work - it always acts like + // ACE_Time_Value::zero is passed - it checks the state once but + // doesn't wait after that. virtual void stop_requested (DWORD control_code); // Called by <handle_control> when a stop/shutdown was requested. @@ -284,13 +292,16 @@ protected: // Called by <handle_control> when a interrogate was requested. protected: - DWORD start_time_; // Estimate of init time needed - SERVICE_STATUS_HANDLE svc_handle_; // Service handle - doesn't need close. - SERVICE_STATUS svc_status_; + DWORD start_time_; + // Estimate of init time needed + SERVICE_STATUS_HANDLE svc_handle_; + // Service handle - doesn't need close. + SERVICE_STATUS svc_status_; - SC_HANDLE svc_sc_handle_;// Service's SCM handle - LPTSTR name_; - LPTSTR desc_; + SC_HANDLE svc_sc_handle_; + // Service's SCM handle + LPTSTR name_; + LPTSTR desc_; }; @@ -349,5 +360,6 @@ extern VOID WINAPI ace_nt_svc_main_##SVCNAME (DWORD dwArgc, LPTSTR *lpszArgv); #include "ace/NT_Service.i" #endif /* __ACE_INLINE__ */ -#endif /* ACE_HAS_WINNT4 */ +#endif /* ACE_WIN32 */ + #endif /* ACE_SERVICE_OBJECT_H */ diff --git a/ace/Process_Manager.cpp b/ace/Process_Manager.cpp index 5d5d14ea1c9..567d2a93af7 100644 --- a/ace/Process_Manager.cpp +++ b/ace/Process_Manager.cpp @@ -168,6 +168,7 @@ ACE_Process_Manager::open (size_t size, { ACE_TRACE ("ACE_Process_Manager::open"); +#if !defined (ACE_LACKS_SETPGID) // Set up a process group so that the thread that opened this // Manager will be able to put children into its own group and wait // for them. @@ -176,6 +177,7 @@ ACE_Process_Manager::open (size_t size, ASYS_TEXT ("%p.\n"), ASYS_TEXT ("ACE_Process_Manager::open: can't create a ") ASYS_TEXT ("process group; some wait functions may fail"))); +#endif /* ACE_LACKS_SETPGID */ if (r) { @@ -252,11 +254,13 @@ ACE_Process_Manager::close (void) { ACE_TRACE ("ACE_Process_Manager::close"); +#if !defined (ACE_WIN32) if (this->reactor ()) { this->reactor ()->remove_handler (this, 0); this->reactor (0); } +#endif /* !ACE_WIN32 */ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1)); @@ -581,6 +585,13 @@ ACE_Process_Manager::remove_proc (size_t i) this->process_table_[i].exit_notify_ = 0; } +#if defined (ACE_WIN32) + ACE_Reactor *r = this->reactor (); + if (r != 0) + r->remove_handler (this->process_table_[i].process_->gethandle (), + ACE_Event_Handler::DONT_CALL); +#endif /* ACE_WIN32 */ + this->process_table_[i].process_->unmanage (); this->process_table_[i].process_ = 0; diff --git a/ace/Task.h b/ace/Task.h index d5a739df0c4..aee510d9901 100644 --- a/ace/Task.h +++ b/ace/Task.h @@ -10,7 +10,7 @@ // Task.h // // = AUTHOR -// Doug Schmidt +// Douglas C. Schmidt <schmidt@cs.wustl.edu> // // ============================================================================ diff --git a/ace/Task_T.h b/ace/Task_T.h index 369032ea953..673c75da2ac 100644 --- a/ace/Task_T.h +++ b/ace/Task_T.h @@ -10,7 +10,7 @@ // Task_T.h // // = AUTHOR -// Doug Schmidt +// Douglas C. Schmidt <schmidt@cs.wustl.edu> // // ============================================================================ |