Re: Stopping PEAK application on SIGINT

Alexey Smishlayev <[email protected]> Wed, 7 Oct 2015 13:09:43 +0300
Newsgroups gmane.comp.python.peak
Message-ID <[email protected]>
This is a multi-part message in MIME format.
--===============0611943626==
Content-Type: multipart/alternative;
	boundary="------------050007010506010104010001"

This is a multi-part message in MIME format.
--------------050007010506010104010001
Content-Type: text/plain; charset=utf-8; format=flowed
Content-Transfer-Encoding: 7bit

Hello!

The application runs successfully with my patch applied and it even 
reacts gracefully to the ^C, so you could say that the desired behavior 
is achieved. I've done it with the following patch:

     def _patchSelector(self):
         from peak.events.io_events import Selector
         from peak.events.io_events import SignalEvents
         Selector.sigsrc = binding.Make(SignalEvents, attrName="sigsrc")
     _patchSelector = binding.Make(_patchSelector, uponAssembly=True)


I guess, I'll leave it for now, but it is not a kind of code I would 
like my colleagues to inherit. If you would provide some directions, I 
will consider fixing and testing PEAK signaling with Twisted support and 
contributing it to your project.


Regards,
Alexey


On 03/10/15 02:07, PJ Eby wrote:
> The issue is that ISelector is a subclass of ISignalSource, and so
> another Selector is created instead of the SignalSource singleton.  I
> don't really have a good way to fix this right now, but as a
> workaround you could monkeypatch to set Selector.sigsrc to
> io_events.SignalEvents and see how that works.  (In truth, I think the
> real problem may be that PEAK's signals support was never tested in
> conjunction with Twisted, and IIRC, the signals support was only
> half-baked to begin with when most work on PEAK ceased 10-11 years
> ago.)
>
> On Fri, Oct 2, 2015 at 6:51 AM, Alexey Smishlayev <[email protected]> wrote:
>> Hello!
>>
>> I tried using pdb today, to some degree of success. Turns out that
>> eventLoop.sigsrc attribute gets an instance of
>> "peak.events.twisted_support.Selector". eventLoop.signals attribute is
>> "binding.Delegate('sigsrc')", so it gets resolved to
>> "peak.events.twisted_support.Selector.signals", which is
>> "binding.Delegate('sigsrc')" - that's where recursion appears.
>>
>> I've gathered some evidence using pdb:
>>> /Library/Python/2.7/site-packages/peak/config/config_components.py(398)lookup()
>> -> for value in iterValues(component, configKey):
>> (Pdb) component
>> <peak.config.config_components.ServiceArea object at 0x108ba3390>
>> (Pdb) configKey
>> config.MultiKey(<class 'peak.binding.interfaces.IComponentFactory'>, <class
>> 'peak.events.interfaces.ISignalSource'>)
>> (Pdb) [x for x in iterValues(component, configKey)]
>> [<class 'peak.events.twisted_support.Selector'>, <class
>> 'peak.events.io_events.SignalEvents'>]
>>
>> --
>>
>>> /Library/Python/2.7/site-packages/peak/config/config_components.py(384)iterValues()
>> -> value = gcd(forObj, configKey)
>> (Pdb) forObj
>> <peak.config.config_components.ServiceArea object at 0x108ba3390>
>> (Pdb) configKey
>> config.MultiKey(<class 'peak.binding.interfaces.IComponentFactory'>, <class
>> 'peak.events.interfaces.ISignalSource'>)
>> (Pdb) gcd
>> <bound method ServiceArea._getConfigData of
>> <peak.config.config_components.ServiceArea object at 0x108ba3390>>
>> (Pdb) gcd(forObj, configKey)
>> <class 'peak.events.twisted_support.Selector'>
>>
>> --
>>
>>> /Library/Python/2.7/site-packages/peak/config/config_components.py(593)_getConfigData()
>> -> value = rule.get()(self, configKey, forObj)
>> (Pdb) rule.get()
>> <function f at 0x1094bfcf8>
>> (Pdb) rule.get()(self, configKey, forObj)
>> <class 'peak.events.twisted_support.Selector'>
>>
>> Unfortunately, my efforts stop here. I have no idea where from this function
>> f appeared in configuration rules, but it creates Selector instance, which
>> messes up the lookup.
>>  From peak.ini: " peak.events.interfaces.ISignalSource =
>> io_events.SignalEvents"
>> I tried grepping "ISignalSource" in my project's directory, but this gives
>> no results.
>>
>>
>> Regards,
>> Alexey
>>
>>
>>
>> On 30/09/15 02:12, PJ Eby wrote:
>>
>> The failure is in trying to retrieve the `signals()` method from the
>> ISignalSource, which should be the io_events.SignalSource singleton.
>> What I don't understand is why it's recursing on the attempt to
>> retrieve the signals attribute.  Specifically, it seems as though this
>> should only be able to happen if trying to load the 'sigsrc' attribute
>> results in an attempt to load the 'signals' attribute.  I would
>> suggest stepping through with the debugger from line 66 of
>> scheduler.py and see if you can tell what's happening there.
>>
>> On Tue, Sep 29, 2015 at 5:56 PM, Alexey Smishlayev <[email protected]> wrote:
>>
>> Hello, Phillip!
>>
>> I use binding.Obtain() on "peak.running.interfaces.IMainLoop", which seem to
>> be instantiating as "peak.running.scheduler.MainLoop" and the
>> "peak.events.interfaces.IEventLoop" is bound to
>> "peak.events.twisted_support.EventLoop". Did not go that far, looked at the
>> PEAK default event loop and couldn't figure out what's wrong (without
>> investgating links in the project's .ini file).
>>
>> Does that mean I cannot use stopOnSignals with the Twisted event loop? Do I
>> have to implement that method? I believe, it's used because Twisted handles
>> TCP communications for us.
>>
>>
>> Best regards,
>> Alexey Smishlayev
>>
>>
>> On 30/09/15 00:27, PJ Eby wrote:
>>
>> Which event loop are you using?  Twisted, the PEAK default, or
>> something else?  The issue here appears to be that the eventLoop
>> property of the MainLoop instance lacks a `signals()` method -- which
>> would seem to mean it doesn't fully implement IEventLoop or is the
>> wrong type of object to start with.
>>
>> On Tue, Sep 29, 2015 at 8:06 AM, Alexey Smishlayev <[email protected]> wrote:
>>
>> Good day everyone!
>> I would like my PEAK application to stop on ^C or SIGINT. Currently, in that
>> case I get an output something like
>>
>> 29.09.2015 14:56:48.179 [DEBUG] Connect.twisted Unexpected error in main
>> loop.
>> 29.09.2015 14:56:48.190 [ERROR] Connect.twisted Traceback (most recent
>> call last):
>> 29.09.2015 14:56:48.190 [ERROR]   File
>> "/Users/alexey/xtech2/tester/build/lib/ank/BBS/CommandBase.py", line 38, in
>> run
>> 29.09.2015 14:56:48.190 [ERROR]     self.mainLoop.run()
>> 29.09.2015 14:56:48.190 [ERROR]   File
>> "/Library/Python/2.7/site-packages/peak/running/scheduler.py", line 78, in
>> run
>> 29.09.2015 14:56:48.190 [ERROR]     return
>> self.eventLoop.runUntil(self.exitCode,True,idle=self.sleep)[0]
>> 29.09.2015 14:56:48.190 [ERROR]   File
>> "/Library/Python/2.7/site-packages/peak/events/twisted_support.py", line
>> 186, in runUntil
>> 29.09.2015 14:56:48.190 [ERROR]     self.reactor.run(False)
>> 29.09.2015 14:56:48.190 [ERROR]   File
>> "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/twisted/internet/base.py",
>> line 1192, in run
>> 29.09.2015 14:56:48.190 [ERROR]     self.mainLoop()
>> 29.09.2015 14:56:48.190 [ERROR] --- <exception caught here> ---
>> 29.09.2015 14:56:48.190 [ERROR]   File
>> "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/twisted/internet/base.py",
>> line 1204, in mainLoop
>> 29.09.2015 14:56:48.190 [ERROR]     self.doIteration(t)
>> 29.09.2015 14:56:48.190 [ERROR]   File
>> "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/twisted/internet/selectreactor.py",
>> line 105, in doSelect
>> 29.09.2015 14:56:48.190 [ERROR]     [], timeout)
>> 29.09.2015 14:56:48.190 [ERROR] exceptions.KeyboardInterrupt:
>>
>> in the log file. In CommandBase.py attribute self.mainloop is defined as
>>
>> from peak.api import binding
>> from peak.running import commands, interfaces
>> class CommandBase(commands.EventDriven):
>>      mainLoop = binding.Obtain(interfaces.IMainLoop)
>>      ...
>>
>> If I set "peak.running.mainLoop.stopOnSignals" in my project's .ini file to
>> anything else except empty tuple, on the application's startup I get the
>> following error (I tried "stopOnSignals = ('SIGINT',)")
>>
>> Traceback (most recent call last):
>>    File "../ank/BBS/Assembler.py", line 370, in run
>>      _exitCode = _root.run()
>>    File "/Library/Python/2.7/site-packages/peak/running/commands.py", line
>> 229, in run
>>      return self._run() or 0
>>    File "/Library/Python/2.7/site-packages/peak/running/commands.py", line
>> 509, in _run
>>      return self.invoke()
>>    File "/Users/alexey/xtech2/tester/build/lib/ank/BBS/CommandBase.py",
>> line 38, in run
>>      self.mainLoop.run()
>>    File "/Library/Python/2.7/site-packages/peak/running/scheduler.py", line
>> 66, in run
>>      handler = self.eventLoop.signals(*self.stopOnSignals)
>>    File "_once.pyx", line 112, in _once.BaseDescriptor.__get__
>>    File "_once.pyx", line 100, in _once.__get__
>>    File "/Library/Python/2.7/site-packages/peak/binding/components.py",
>> line 682, in delegate
>>      return getattr(getattr(s,delegateAttr),a)
>>    File "_once.pyx", line 112, in _once.BaseDescriptor.__get__
>>    File "_once.pyx", line 100, in _once.__get__
>>    File "/Library/Python/2.7/site-packages/peak/binding/components.py",
>> line 682, in delegate
>>      return getattr(getattr(s,delegateAttr),a)
>>    File "_once.pyx", line 88, in _once.BaseDescriptor.__get__
>> AttributeError: ('Recursive attempt to compute attribute', 'signals')
>>
>> How do I do everything correctly?
>>
>>
>> Best regards,
>> Alexey Smishlayev
>>
>> _______________________________________________
>> PEAK mailing list
>> [email protected]
>> http://www.eby-sarna.com/mailman/listinfo/peak
>>
>>
>>
>> _______________________________________________
>> PEAK mailing list
>> [email protected]
>> http://www.eby-sarna.com/mailman/listinfo/peak
>>
>>
>>
>> _______________________________________________
>> PEAK mailing list
>> [email protected]
>> http://www.eby-sarna.com/mailman/listinfo/peak


--------------050007010506010104010001
Content-Type: text/html; charset=utf-8
Content-Transfer-Encoding: quoted-printable

<html>
  <head>
    <meta content=3D"text/html; charset=3Dutf-8" http-equiv=3D"Content-Ty=
pe">
  </head>
  <body bgcolor=3D"#FFFFFF" text=3D"#000000">
    Hello!<br>
    <br>
    The application runs successfully with my patch applied and it even
    reacts gracefully to the ^C, so you could say that the desired
    behavior is achieved. I've done it with the following patch:<br>
    <br>
    <meta http-equiv=3D"content-type" content=3D"text/html; charset=3Dutf=
-8">
    =C2=A0=C2=A0=C2=A0 def _patchSelector(self):<br>
    =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 from peak.events.io_events=
 import Selector<br>
    =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 from peak.events.io_events=
 import SignalEvents<br>
    =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 Selector.sigsrc =3D bindin=
g.Make(SignalEvents,
    attrName=3D"sigsrc")<br>
    =C2=A0=C2=A0=C2=A0 _patchSelector =3D binding.Make(_patchSelector, up=
onAssembly=3DTrue)<br>
    <br>
    <br>
    I guess, I'll leave it for now, but it is not a kind of code I would
    like my colleagues to inherit. If you would provide some directions,
    I will consider fixing and testing PEAK signaling with Twisted
    support and contributing it to your project.<br>
    <br>
    <br>
    Regards,<br>
    Alexey<br>
    <br>
    <br>
    <div class=3D"moz-cite-prefix">On 03/10/15 02:07, PJ Eby wrote:<br>
    </div>
    <blockquote
cite=3D"mid:CALeMXf7BQh2xc1=3D9xO=3DKuoz8TpSLDfQiZbbTNJeYoUKi0t5jjg@mail.=
gmail.com"
      type=3D"cite">
      <pre wrap=3D"">The issue is that ISelector is a subclass of ISignal=
Source, and so
another Selector is created instead of the SignalSource singleton.  I
don't really have a good way to fix this right now, but as a
workaround you could monkeypatch to set Selector.sigsrc to
io_events.SignalEvents and see how that works.  (In truth, I think the
real problem may be that PEAK's signals support was never tested in
conjunction with Twisted, and IIRC, the signals support was only
half-baked to begin with when most work on PEAK ceased 10-11 years
ago.)

On Fri, Oct 2, 2015 at 6:51 AM, Alexey Smishlayev <a class=3D"moz-txt-lin=
k-rfc2396E" href=3D"mailto:[email protected]">&lt;[email protected]&gt;</a>=
 wrote:
</pre>
      <blockquote type=3D"cite">
        <pre wrap=3D"">Hello!

I tried using pdb today, to some degree of success. Turns out that
eventLoop.sigsrc attribute gets an instance of
"peak.events.twisted_support.Selector". eventLoop.signals attribute is
"binding.Delegate('sigsrc')", so it gets resolved to
"peak.events.twisted_support.Selector.signals", which is
"binding.Delegate('sigsrc')" - that's where recursion appears.

I've gathered some evidence using pdb:
</pre>
        <blockquote type=3D"cite">
          <pre wrap=3D"">
/Library/Python/2.7/site-packages/peak/config/config_components.py(398)lo=
okup()
</pre>
        </blockquote>
        <pre wrap=3D"">-&gt; for value in iterValues(component, configKey=
):
(Pdb) component
&lt;peak.config.config_components.ServiceArea object at 0x108ba3390&gt;
(Pdb) configKey
config.MultiKey(&lt;class 'peak.binding.interfaces.IComponentFactory'&gt;=
, &lt;class
'peak.events.interfaces.ISignalSource'&gt;)
(Pdb) [x for x in iterValues(component, configKey)]
[&lt;class 'peak.events.twisted_support.Selector'&gt;, &lt;class
'peak.events.io_events.SignalEvents'&gt;]

--

</pre>
        <blockquote type=3D"cite">
          <pre wrap=3D"">
/Library/Python/2.7/site-packages/peak/config/config_components.py(384)it=
erValues()
</pre>
        </blockquote>
        <pre wrap=3D"">-&gt; value =3D gcd(forObj, configKey)
(Pdb) forObj
&lt;peak.config.config_components.ServiceArea object at 0x108ba3390&gt;
(Pdb) configKey
config.MultiKey(&lt;class 'peak.binding.interfaces.IComponentFactory'&gt;=
, &lt;class
'peak.events.interfaces.ISignalSource'&gt;)
(Pdb) gcd
&lt;bound method ServiceArea._getConfigData of
&lt;peak.config.config_components.ServiceArea object at 0x108ba3390&gt;&g=
t;
(Pdb) gcd(forObj, configKey)
&lt;class 'peak.events.twisted_support.Selector'&gt;

--

</pre>
        <blockquote type=3D"cite">
          <pre wrap=3D"">
/Library/Python/2.7/site-packages/peak/config/config_components.py(593)_g=
etConfigData()
</pre>
        </blockquote>
        <pre wrap=3D"">-&gt; value =3D rule.get()(self, configKey, forObj=
)
(Pdb) rule.get()
&lt;function f at 0x1094bfcf8&gt;
(Pdb) rule.get()(self, configKey, forObj)
&lt;class 'peak.events.twisted_support.Selector'&gt;

Unfortunately, my efforts stop here. I have no idea where from this funct=
ion
f appeared in configuration rules, but it creates Selector instance, whic=
h
messes up the lookup.
>From peak.ini: " peak.events.interfaces.ISignalSource =3D
io_events.SignalEvents"
I tried grepping "ISignalSource" in my project's directory, but this give=
s
no results.


Regards,
Alexey



On 30/09/15 02:12, PJ Eby wrote:

The failure is in trying to retrieve the `signals()` method from the
ISignalSource, which should be the io_events.SignalSource singleton.
What I don't understand is why it's recursing on the attempt to
retrieve the signals attribute.  Specifically, it seems as though this
should only be able to happen if trying to load the 'sigsrc' attribute
results in an attempt to load the 'signals' attribute.  I would
suggest stepping through with the debugger from line 66 of
scheduler.py and see if you can tell what's happening there.

On Tue, Sep 29, 2015 at 5:56 PM, Alexey Smishlayev <a class=3D"moz-txt-li=
nk-rfc2396E" href=3D"mailto:[email protected]">&lt;[email protected]&gt;</a=
> wrote:

Hello, Phillip!

I use binding.Obtain() on "peak.running.interfaces.IMainLoop", which seem=
 to
be instantiating as "peak.running.scheduler.MainLoop" and the
"peak.events.interfaces.IEventLoop" is bound to
"peak.events.twisted_support.EventLoop". Did not go that far, looked at t=
he
PEAK default event loop and couldn't figure out what's wrong (without
investgating links in the project's .ini file).

Does that mean I cannot use stopOnSignals with the Twisted event loop? Do=
 I
have to implement that method? I believe, it's used because Twisted handl=
es
TCP communications for us.


Best regards,
Alexey Smishlayev


On 30/09/15 00:27, PJ Eby wrote:

Which event loop are you using?  Twisted, the PEAK default, or
something else?  The issue here appears to be that the eventLoop
property of the MainLoop instance lacks a `signals()` method -- which
would seem to mean it doesn't fully implement IEventLoop or is the
wrong type of object to start with.

On Tue, Sep 29, 2015 at 8:06 AM, Alexey Smishlayev <a class=3D"moz-txt-li=
nk-rfc2396E" href=3D"mailto:[email protected]">&lt;[email protected]&gt;</a=
> wrote:

Good day everyone!
I would like my PEAK application to stop on ^C or SIGINT. Currently, in t=
hat
case I get an output something like

29.09.2015 14:56:48.179 [DEBUG] Connect.twisted Unexpected error in main
loop.
29.09.2015 14:56:48.190 [ERROR] Connect.twisted Traceback (most recent
call last):
29.09.2015 14:56:48.190 [ERROR]   File
"/Users/alexey/xtech2/tester/build/lib/ank/BBS/CommandBase.py", line 38, =
in
run
29.09.2015 14:56:48.190 [ERROR]     self.mainLoop.run()
29.09.2015 14:56:48.190 [ERROR]   File
"/Library/Python/2.7/site-packages/peak/running/scheduler.py", line 78, i=
n
run
29.09.2015 14:56:48.190 [ERROR]     return
self.eventLoop.runUntil(self.exitCode,True,idle=3Dself.sleep)[0]
29.09.2015 14:56:48.190 [ERROR]   File
"/Library/Python/2.7/site-packages/peak/events/twisted_support.py", line
186, in runUntil
29.09.2015 14:56:48.190 [ERROR]     self.reactor.run(False)
29.09.2015 14:56:48.190 [ERROR]   File
"/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/pyth=
on/twisted/internet/base.py",
line 1192, in run
29.09.2015 14:56:48.190 [ERROR]     self.mainLoop()
29.09.2015 14:56:48.190 [ERROR] --- &lt;exception caught here&gt; ---
29.09.2015 14:56:48.190 [ERROR]   File
"/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/pyth=
on/twisted/internet/base.py",
line 1204, in mainLoop
29.09.2015 14:56:48.190 [ERROR]     self.doIteration(t)
29.09.2015 14:56:48.190 [ERROR]   File
"/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/pyth=
on/twisted/internet/selectreactor.py",
line 105, in doSelect
29.09.2015 14:56:48.190 [ERROR]     [], timeout)
29.09.2015 14:56:48.190 [ERROR] exceptions.KeyboardInterrupt:

in the log file. In CommandBase.py attribute self.mainloop is defined as

from peak.api import binding
from peak.running import commands, interfaces
class CommandBase(commands.EventDriven):
    mainLoop =3D binding.Obtain(interfaces.IMainLoop)
    ...

If I set "peak.running.mainLoop.stopOnSignals" in my project's .ini file =
to
anything else except empty tuple, on the application's startup I get the
following error (I tried "stopOnSignals =3D ('SIGINT',)")

Traceback (most recent call last):
  File "../ank/BBS/Assembler.py", line 370, in run
    _exitCode =3D _root.run()
  File "/Library/Python/2.7/site-packages/peak/running/commands.py", line
229, in run
    return self._run() or 0
  File "/Library/Python/2.7/site-packages/peak/running/commands.py", line
509, in _run
    return self.invoke()
  File "/Users/alexey/xtech2/tester/build/lib/ank/BBS/CommandBase.py",
line 38, in run
    self.mainLoop.run()
  File "/Library/Python/2.7/site-packages/peak/running/scheduler.py", lin=
e
66, in run
    handler =3D self.eventLoop.signals(*self.stopOnSignals)
  File "_once.pyx", line 112, in _once.BaseDescriptor.__get__
  File "_once.pyx", line 100, in _once.__get__
  File "/Library/Python/2.7/site-packages/peak/binding/components.py",
line 682, in delegate
    return getattr(getattr(s,delegateAttr),a)
  File "_once.pyx", line 112, in _once.BaseDescriptor.__get__
  File "_once.pyx", line 100, in _once.__get__
  File "/Library/Python/2.7/site-packages/peak/binding/components.py",
line 682, in delegate
    return getattr(getattr(s,delegateAttr),a)
  File "_once.pyx", line 88, in _once.BaseDescriptor.__get__
AttributeError: ('Recursive attempt to compute attribute', 'signals')

How do I do everything correctly?


Best regards,
Alexey Smishlayev

_______________________________________________
PEAK mailing list
<a class=3D"moz-txt-link-abbreviated" href=3D"mailto:[email protected]">=
[email protected]</a>
<a class=3D"moz-txt-link-freetext" href=3D"http://www.eby-sarna.com/mailm=
an/listinfo/peak">http://www.eby-sarna.com/mailman/listinfo/peak</a>



_______________________________________________
PEAK mailing list
<a class=3D"moz-txt-link-abbreviated" href=3D"mailto:[email protected]">=
[email protected]</a>
<a class=3D"moz-txt-link-freetext" href=3D"http://www.eby-sarna.com/mailm=
an/listinfo/peak">http://www.eby-sarna.com/mailman/listinfo/peak</a>



_______________________________________________
PEAK mailing list
<a class=3D"moz-txt-link-abbreviated" href=3D"mailto:[email protected]">=
[email protected]</a>
<a class=3D"moz-txt-link-freetext" href=3D"http://www.eby-sarna.com/mailm=
an/listinfo/peak">http://www.eby-sarna.com/mailman/listinfo/peak</a>
</pre>
      </blockquote>
      <pre wrap=3D"">
</pre>
    </blockquote>
    <br>
  </body>
</html>

--------------050007010506010104010001--

--===============0611943626==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

_______________________________________________
PEAK mailing list
[email protected]
http://www.eby-sarna.com/mailman/listinfo/peak
--===============0611943626==--