Re: Stopping PEAK application on SIGINT

Alexey Smishlayev <[email protected]> Fri, 2 Oct 2015 13:51:54 +0300
Newsgroups gmane.comp.python.peak
Message-ID <[email protected]>
This is a multi-part message in MIME format.
--===============0559412773==
Content-Type: multipart/alternative;
	boundary="------------090100030509070203080809"

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

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


--------------090100030509070203080809
Content-Type: text/html; charset=utf-8
Content-Transfer-Encoding: 7bit

<html>
  <head>
    <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    Hello!<br>
    <br>
    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.<br>
    <br>
    I've gathered some evidence using pdb:<br>
    &gt;
/Library/Python/2.7/site-packages/peak/config/config_components.py(398)lookup()<br>
    -&gt; for value in iterValues(component, configKey):<br>
    (Pdb) component<br>
    &lt;peak.config.config_components.ServiceArea object at
    0x108ba3390&gt;<br>
    (Pdb) configKey<br>
    config.MultiKey(&lt;class
    'peak.binding.interfaces.IComponentFactory'&gt;, &lt;class
    'peak.events.interfaces.ISignalSource'&gt;)<br>
    (Pdb) [x for x in iterValues(component, configKey)]<br>
    [&lt;class 'peak.events.twisted_support.Selector'&gt;, &lt;class
    'peak.events.io_events.SignalEvents'&gt;]<br>
    <br>
    --<br>
    <br>
    &gt;
/Library/Python/2.7/site-packages/peak/config/config_components.py(384)iterValues()<br>
    -&gt; value = gcd(forObj, configKey)<br>
    (Pdb) forObj<br>
    &lt;peak.config.config_components.ServiceArea object at
    0x108ba3390&gt;<br>
    (Pdb) configKey<br>
    config.MultiKey(&lt;class
    'peak.binding.interfaces.IComponentFactory'&gt;, &lt;class
    'peak.events.interfaces.ISignalSource'&gt;)<br>
    (Pdb) gcd<br>
    &lt;bound method ServiceArea._getConfigData of
    &lt;peak.config.config_components.ServiceArea object at
    0x108ba3390&gt;&gt;<br>
    (Pdb) gcd(forObj, configKey)<br>
    &lt;class 'peak.events.twisted_support.Selector'&gt;<br>
    <br>
    --<br>
    <br>
    &gt;
/Library/Python/2.7/site-packages/peak/config/config_components.py(593)_getConfigData()<br>
    -&gt; value = rule.get()(self, configKey, forObj)<br>
    (Pdb) rule.get()<br>
    &lt;function f at 0x1094bfcf8&gt;<br>
    (Pdb) rule.get()(self, configKey, forObj)<br>
    &lt;class 'peak.events.twisted_support.Selector'&gt;<br>
    <br>
    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.<br>
    From peak.ini: "
    <meta http-equiv="content-type" content="text/html; charset=utf-8">
    peak.events.interfaces.ISignalSource = io_events.SignalEvents"<br>
    I tried grepping "ISignalSource" in my project's directory, but this
    gives no results.<br>
    <br>
    <br>
    Regards,<br>
    Alexey<br>
    <br>
    <br>
    <div class="moz-cite-prefix">On 30/09/15 02:12, PJ Eby wrote:<br>
    </div>
    <blockquote
cite="mid:CALeMXf64pWumhieSYiamsZWVUbvaYhf8QvMGzFX_5itkqGCzhA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org"
      type="cite">
      <pre wrap="">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="moz-txt-link-rfc2396E" href="mailto:[email protected]">&lt;[email protected]&gt;</a> wrote:
</pre>
      <blockquote type="cite">
        <pre wrap="">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 <a class="moz-txt-link-rfc2396E" href="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 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] --- &lt;exception caught here&gt; ---
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
<a class="moz-txt-link-abbreviated" href="mailto:[email protected]">[email protected]</a>
<a class="moz-txt-link-freetext" href="http://www.eby-sarna.com/mailman/listinfo/peak">http://www.eby-sarna.com/mailman/listinfo/peak</a>



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

--------------090100030509070203080809--

--===============0559412773==
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
--===============0559412773==--