Hey, DK.
Hopefully I'm not introducing a big leak here, but give this a try:
Index: pycontext.cc
===================================================================
--- pycontext.cc        (revision 2)
+++ pycontext.cc        (working copy)
@@ -132,6 +132,7 @@

     if(sfe.python_arg){
         pyglue_setattr_string(proxy, "pyevent", sfe.python_arg);
+        Py_INCREF(sfe.python_arg);
     }else{
         pyglue_setattr_string(proxy, "pyevent", Py_None);
         vlog().log(vlog().get_module_val("pyrt"), Vlog::LEVEL_ERR,

-- Murphy

>I followed this approach and it seems it doesn't work when propagating an event through event handler chain. >I encountered segfault and I guess it's related to object reference counting.
>
>This is a simplified version of what I did (and this simplified version also causes segault.)
>(Sorry for copy-paste a long code.)
>
>I don't care about the order of event receivers in this example.
>When you see a log message at the bottom, the first receiver successfully accessed the event object, but segfault happens when the second receiver tries to read it.
>
>If I enable self.event = event.pyevent in event handlers below, it does not crash.
>That's why I suspect it's about reference counting.
>
>Any idea about this?
>Please let me know if this is not a good way to passing an event through a handler chain.
>
>
>==== netapps/event_test/event.py ====
>EVENT_NAME = 'DKEvent'
>
>class DKEvent:
>    def __init__(self):
>        self.var = 1234
>
>
>==== netapps/event_test/trigger.py =====
>from nox.lib.core import Component, pyevent, CONTINUE, STOP
>from nox.netapps.event_test import event
>
>class trigger(Component):
>
>    def __init__(self, ctxt):
>        Component.__init__(self, ctxt)
>
>    def install(self):
>        self.register_python_event(event.EVENT_NAME)
>        self.register_for_packet_in(self.handle_packet_in)
>
>    def getInterface(self):
>        return str(trigger)
>
> def handle_packet_in(self, dpid, inport, reason, len, bufid, packet):
>        # Create FlowInEvent and pot it.
>        e = event.DKEvent()
>        self.post(pyevent(event.EVENT_NAME, e))
>
>
>def getFactory():
>    class Factory:
>        def instance(self, ctxt):
>            return trigger(ctxt)
>
>    return Factory()
>
>
>==== netapps/event_test/receiver1.py =====
>
>from nox.lib.core import Component, pyevent, CONTINUE, STOP
>from nox.netapps.event_test import event
>
>class receiver1(Component):
>
>    def __init__(self, ctxt):
>        Component.__init__(self, ctxt)
>
>    def install(self):
>        self.register_handler(event.EVENT_NAME,
>                              self.handle_dk_event)
>
>    def getInterface(self):
>        return str(receiver1)
>
>    def handle_dk_event(self, event):
>        #self.event = event.pyevent
>        print "-- receiver1:", event.pyevent
>        return CONTINUE
>
>
>def getFactory():
>    class Factory:
>        def instance(self, ctxt):
>            return receiver1(ctxt)
>
>    return Factory()
>
>
>==== netapps/event_test/receiver2.py =====
>(The same as receiver1 except s/receiver1/receiver2/g)
>
>
>
>=== Log from ./nox_core -v -i ptcp: trigger receiver1 receiver2 ===
>
>-- receiver1: <nox.netapps.event_test.event.DKEvent instance at 0x9b19e2c>
>Caught signal 11.
>  0x401acec9   64 (vigil::fault_handler(int)+0x49)
>  0x4001c400 3054704048 (__kernel_sigreturn+0x0)
>  0x40a8b091   48 (PyFile_WriteObject+0xb1)
>  0x40af80b4  720 (PyEval_EvalFrameEx+0x4634)
> /home/ripcord/ripcord-nox/build/src/nox/netapps/event_test/ receiver2.py:16: handle_dk_event > 'self' : <nox.netapps.event_test.receiver2.receiver2 instance at 0x9b19b2c> 'event' : <nox.coreapps.pyrt.pycomponent.pyevent; proxy of <Swig Object of type 'pyevent *' at 0x9b443c8> > 0x40afaedd 112 (PyEval_EvalCodeEx+0x6ad)
>  0x40a915ea
>  0x40a6da17   32 (PyObject_Call+0x37)
>  0x40a75855
>  0x40a6da17   32 (PyObject_Call+0x37)
>  0x40af2c7c   32 (PyEval_CallObjectWithKeywords+0x7c)
>  0x40a6dbfc   32 (PyObject_CallObject+0x2c)
> 0x419a80e9 176 (vigil ::applications::Python_event_manager::call_python_handler(vigil::Event const&, boost::intrusive_ptr<_object>&)+0x5b9) > 0x419c27be 32 (boost ::detail ::function ::function_obj_invoker1<boost::_bi::bind_t<vigil::Disposition, boost::_mfi::mf2<vigil::Disposition, vigil::applications::Python_event_manager, vigil::Event const&, boost::intrusive_ptr<_object>&>, boost ::_bi ::list3<boost::_bi::value<vigil::applications::Python_event_manager*>, boost::arg<1>, boost::_bi::value<boost::intrusive_ptr<_object> > > >, vigil::Disposition, vigil::Event const&>::invoke(boost::detail::function::function_buffer&, vigil::Event const&)+0x2e) > 0x401a6ad3 64 (boost::function1<vigil::Disposition, vigil::Event const&, std::allocator<void> >::operator()(vigil::Event const&) const +0x33) > 0x401a48dc 2272 (vigil::Event_dispatcher::dispatch(vigil::Event const&)+0x4bc)
>  0x401a5247   64 (vigil::Event_dispatcher::poll()+0x67)
>  0x401dc3de
>  0x401dcaef
>  0x401dd7d9   64 (vigil::Poll_loop_impl::run()+0xb9)
>  0x401dd92f   16 (vigil::Poll_loop::run()+0x1f)
>  0x4011d450   16 (vigil::nox::run()+0x20)
>  0x080578de 5920 (main+0x234e)
>  0x40380455  112 (__libc_start_main+0xe5)
>Segmentation fault (core dumped)
>
>
>
>
>
>
>
>On Jan 4, 2010, at 5:46 PM, David Erickson wrote:
>
>> As a clarification for anyone that reads this down the road, it turns out that the python_arg is where you put a python object that you will retrieve when handling a posted event. IE:
>>
>> self.post(pyevent("name here", my_obj))
>>
>> then to retrieve my_obj from a handler
>>
>> def handle_event(self, event):
>>  event.pyevent
>>
>> Where the pyevent member is the object you posted originally. If you try and add attributed to the actual pyevent object you post they do not make it through to the handler.
>>
>> -David
>>
>> Martin Casado wrote:
>>> This use to be required so that python-only state was not passed into C++ but I don't believe it is actually used anymore. You can safely ignore the message. >>>> Tried this and it worked like a charm. I did see an error message in the log:
>>>>
>>>> 00042|pyrt|ERR:Pyevent without internal python_arg set
>>>>
>>>> So I changed my event posting to:
>>>> self.post(FlowOutEvent("flowoutevent", 1))
>>>>
>>>> Which solved it. I took a look at the source but couldn't reason out what the python_arg is used for?
>>>>
>>>> Thanks,
>>>> David
>>>>
>>>>
>>>> Martin Casado wrote:
>>>>> Actually looking at the code, this should already be supported.
>>>>>
>>>>> Try registering with "register_python_event(name)". See with context.i.
>>>>>
>>>>> This registers the default python converter and should allow you to create and post python only events without writing any c++.
>>>>>
>>>>> .martin
>>>>>
>>>>>
>>>>>> Hi David
>>>>>>
>>>>>> I'm also interested in getting python-only events working. Were you able to get past this issue?
>>>>>>
>>>>>> Thanks,
>>>>>> Brandon
>>>>>>
>>>>>> On Wed, Dec 16, 2009 at 8:08 PM, David Erickson <derickso at stanford.edu <mailto:derickso at stanford.edu>> wrote:
>>>>>>
>>>>>>    Martin Casado wrote:
>>>>>>
>>>>>> I don't see where you are setting the name of the event you're
>>>>>>        posting.
>>>>>>
>>>>>>
>>>>>>    That could be important ;)  Changed the code to be
>>>>>> self.post(FlowOutEvent("flowoutevent")), now I get the following:
>>>>>>
>>>>>>    00041|flowinstaller|ERR:flowoutevent posted
>>>>>> 00042|pyrt|ERR:flowoutevent has no C++ to Python event converter.
>>>>>>
>>>>>>    -David
>>>>>>
>>>>>>
>>>>>>    _______________________________________________
>>>>>>    nox-dev mailing list
>>>>>>    nox-dev at noxrepo.org <mailto:nox-dev at noxrepo.org>
>>>>>>    http://noxrepo.org/mailman/listinfo/nox-dev_noxrepo.org
>>>>>>
>>>>>>
>>>>>
>>>>>
>>>>
>>
>>
>> _______________________________________________
>> nox-dev mailing list
>> nox-dev at noxrepo.org
>> http://noxrepo.org/mailman/listinfo/nox-dev_noxrepo.org


_______________________________________________
nox-dev mailing list
nox-dev@noxrepo.org
http://noxrepo.org/mailman/listinfo/nox-dev_noxrepo.org

Reply via email to