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