summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorschmidt <douglascraigschmidt@users.noreply.github.com>2000-01-18 04:16:59 +0000
committerschmidt <douglascraigschmidt@users.noreply.github.com>2000-01-18 04:16:59 +0000
commitd4de8a9e6000f13de74c9050455bd38a77fffdbe (patch)
tree9d67308398a783953b71533e9cc07f60671a1239
parentf0b6139ba32b4246dd464778084114cb719db4fc (diff)
downloadATCD-d4de8a9e6000f13de74c9050455bd38a77fffdbe.tar.gz
ChangeLogTag:Mon Jan 17 18:03:17 2000 Douglas C. Schmidt <schmidt@tango.cs.wustl.edu>
-rw-r--r--ChangeLog66
-rw-r--r--ChangeLogs/ChangeLog-02a66
-rw-r--r--ChangeLogs/ChangeLog-03a66
-rw-r--r--THANKS5
-rw-r--r--ace/NT_Service.cpp371
-rw-r--r--ace/NT_Service.h254
-rw-r--r--ace/Process_Manager.cpp11
-rw-r--r--ace/Task.h2
-rw-r--r--ace/Task_T.h2
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.
diff --git a/THANKS b/THANKS
index e012d4e756b..f5c3979de03 100644
--- a/THANKS
+++ b/THANKS
@@ -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>
//
// ============================================================================