> [For some reason Tim's original still hasn't arrived!]
You know, from my POV that statement is pretty mysterious, since you
seem to be replying to my email here <wink>.
>> I'm trying to build a new ZRS release. Trying to stop the ZRS service
>> now "suddenly and for no reason at all" <wink> logs an error, because
>> I believe its onStop() method is getting called twice now, but used to
>> be called only once. That's no good for ZRS, because its onStop
>> method makes a connection to a special "shutdown port", and ZRS proper
>> responds by shutting ZRS down. The socket goes away along with it, so
>> trying to connect to the shutdown port a second time raises an
>> I'm not entirely sure why this didn't used to happen. I'm guessing
>> that a stop request with the current code:
>> 1. Triggers SvcStop, which calls onStop() and sets hWaitStop.
>> 2. Setting hWaitStop in turn triggers the WaitForMultipleObjects in run(),
>> and then that calls SvcStop again (which calls onStop() again).
>> Anyway, is this bug or feature? If it's a feature, I can make the ZRS
>> subclass onStop() methods safe to call multiple times. It doesn't
>> _feel_ like a feature, though <wink>.
> From the sounds of things it is a bug <wink>.
> FYI, SvcStop is called by the (Python win32serviceutil) framework when an
> external request comes in to stop the service.
I think that's my #1 above, and I think that part works fine here.
The tracebacks I see have run() in the call stack, which is why I
guess #2 is doing SvcStop it a second time.
> However, a service can stop also stop by its own accord.
I don't think ZRS ever does that, and am not sure how I could write
code to do it. Does a Zope service ever decide to "stop by its own
> The question, then, is under what cases should the onStop() calls be made? It
> sounds to me like you want it called only when that external request comes in.
Maybe. In the end, by whatever means a service gets shut down
(external, internal, whatever), I want to see the subclass onStop()
method called exactly once.
But that's mostly because that's what "used to happen" for the two
ZRS-related services, not because it's a Holy Principle I'd fight to
death to defend <wink>.
> Assuming that is the case, I believe both explicit calls to SvcStop() are
> bogus and can be removed completely. The report of
> SERVICE_STOP_PENDING will happen as soon as these functions return
> False. In both cases, it is not necessary to set hWaitStop as nothing is
> to wait on it once these lines get hit. It seems we also don't want onStop()
> called at these times, so nothing the function does is necessary at those
> Also FYI, service.py is identical in both 2.7 and 2.8, so can be copied
> between them. I believe the diff you want is simply:
> RCS file: /cvs-repository/Zope/lib/python/nt_svcutils/Attic/service.py,v
> retrieving revision 18.104.22.168
> diff -u -r22.214.171.124 service.py
> --- service.py 14 Apr 2005 01:47:48 -0000 126.96.36.199
> +++ service.py 19 Apr 2005 04:48:18 -0000
> @@ -234,7 +234,6 @@
> if rc == win32event.WAIT_OBJECT_0:
> # user sent a stop service request
> - self.SvcStop()
> keep_running = False
> elif rc == win32event.WAIT_OBJECT_0 + 1:
> # user did not send a service stop request, but
> @@ -261,7 +260,6 @@
> # this was an abormal shutdown.
> if self.backoff_cumulative > BACKOFF_MAX:
> self.error("restarting too frequently; quit")
> - self.SvcStop()
> return False
> self.warning("sleep %s to avoid rapid restarts"
> % self.backoff_interval)
> That seems to work fine here.
Seems to work fine for the ZRS-related services too, although I didn't
get into the "restarting too frequently" branch. Thank you. If
nobody objects in the next 10 minutes, then, I'll check this in (and
port to Zope trunk (2.8) too).
Zope-Checkins maillist - Zope-Checkins@zope.org