Re: [g-a-devel] Need ATK experienced help



Li,

Here's what I think is happening:

1. My AT-SPI client connects and dumps the AT-SPI tree
   of the system.
2. As the client walks the AT-SPI tree of my Python
   app, my ATK code creates a tree of ATK objects.
3. The AT-SPI client exits.
4. Sensing that the client has exited, some part of
   the AT-SPI, AT-SPI-Registryd, Bonobo, Orbit system
   starts trying to reclaim the AtkObjects in my tree!

My question is step 4 basically correct?

Is there a signal or callback my ATK code should be
listening for that would tell me that all the AtkObject
nodes I have are being reclaimed and I should clean up
my data structures?

During steps 1-4 above, my Python GUI app has not
changed.  So it seems odd to me that the data
structures need to be cleaned up -- they are
still valid.

-Sam

PS: Here's the evidence I used to reach the above
conclusions.

Evidence
========
PAPI requires my ATK code call a PAPI function
(papi.atk.iterate()) from my main GUI loop, during idle
time(*).  I put some checking code before and after
this call, and verified that during one of these calls
one of my AtkObjects was getting trashed.

The code in papi.atk.iterate() basically consists of this:

g_main_context_iteration (g_main_context_default (), FALSE);

Which doesn't really answer the question "who is trashing
my AtkObject and why?"

So I found a Linux routine, mprotect() that allowed me to
set the memory covering my AtkObject to read-only.  So now
my iteration routine looked like this:

    protect(targetObj);    // set memory read-only
    papi.atk.iterate();
    unprotect(targetObj);  // read-write

Eventually, I got the SIGSEGV I was looking for.  We had some
code that registered a SIGSEGV signal handler and printed a
call stack, so I brought that into play.  Here's the call stack,
the caller is shown underneath the callee:

/usr/lib/python2.6/site-packages/papi/atk.so(print_traceback+0x30)
[0xb7403a3e]
/usr/lib/python2.6/site-packages/papi/atk.so [0xb7403aa6]
[0xb7ee8400]
/lib/libglib-2.0.so.0(g_atomic_int_compare_and_exchange+0xf)
[0xb776a5d0]
/lib/libgobject-2.0.so.0(g_object_unref+0x62) [0xb739bc97]
/usr/lib/libspi.so.0 [0xb6dc5130]
/lib/libgobject-2.0.so.0(g_object_unref+0x74) [0xb739bca9]
/usr/lib/libbonobo-2.so.0(bonobo_object_unref+0x359) [0xb6d4e857]
/usr/lib/libbonobo-2.so.0 [0xb6d4e960]
/usr/lib/libbonobo-activation.so.4(_ORBIT_skel_small_Bonobo_Unknown_unre
f+0xf) [0xb6d19b2f]
/usr/lib/libORBit-2.so.0 [0xb6ce2bd9]
/usr/lib/libORBit-2.so.0(ORBit_OAObject_invoke+0x1f) [0xb6ce7416]
/usr/lib/libORBit-2.so.0(ORBit_small_invoke_adaptor+0x367) [0xb6cd881a]
/usr/lib/libORBit-2.so.0 [0xb6ce5c4d]
/usr/lib/libORBit-2.so.0 [0xb6ce5eb3]
/usr/lib/libORBit-2.so.0 [0xb6ce616f]
/usr/lib/libORBit-2.so.0(ORBit_handle_request+0x19e) [0xb6ce78f7]
/usr/lib/libORBit-2.so.0(giop_connection_handle_input+0x403)
[0xb6cd5833]
/usr/lib/libORBit-2.so.0 [0xb6cec7b7]
/usr/lib/libORBit-2.so.0 [0xb6ceec37]
/lib/libglib-2.0.so.0(g_main_context_dispatch+0x19b) [0xb778868f]
/lib/libglib-2.0.so.0 [0xb778a63c]
/lib/libglib-2.0.so.0(g_main_context_iteration+0x75) [0xb778a733]
/usr/lib/python2.6/site-packages/papi/atk.so [0xb74050f1]
/usr/lib/libpython2.6.so.1.0(PyEval_EvalFrameEx+0x40ad) [0xb7dfed1a]

I found this stack very interesting.  First, if you look at
the bottom you see this:

/lib/libglib-2.0.so.0(g_main_context_iteration+0x75) [0xb778a733]

That is the routine papi.atk.iterate() called.  For some reason
this calls other stuff and eventually we get towards the top where
we see lots of calls on routines with names ending in "_unref".
Finally, the routine that faulted, g_atomic_int_compare_and_exchange,
was probably trying to lower the reference count in my AtkObject.
Presumably, if that count goes to zero, my AtkObject gets reclaimed
and the "reclaiming" is what is trashing my object.


(*)Tka11y adds ATK support for Tkinter using PAPI.
The author has an interesting strategy for reducing
the overhead of calling papi.atk.iterate().


-----Original Message-----
From: Li Yuan sun com [mailto:Li Yuan sun com] 
Sent: Wednesday, September 02, 2009 2:58 AM
To: Quiring, Sam
Cc: Gnome-accessibility-devel gnome org
Subject: Re: [g-a-devel] Need ATK experienced help

Hi Quiring,

How did you implement ref_child function? Is there a cache?

Li

On Tue, 2009-09-01 at 14:21 -0700, Quiring, Sam wrote:
> Greetings,
>  
> I'm adding ATK support to a Python platform that implements its own
> graphics library from scratch.  I'm using Papi, which has been really
> excellent.
>  
> I've just finished implementing some of the ATK support.  ATK objects
> (actually, papi.atk.AtkObject's) are created on demand.  When an
> ATK request comes in for the Nth child of an ATK node (via the ATK
> callback AtkObjectClass.ref_child), I examine the associated GUI
> node's children, find the Nth one, and create a corresponding ATK node
> for it, which I pass back to the caller.
>  
> One client I'm using to test this is an AT-SPI dump program I wrote a
> while ago.  It dumps the entire AT-SPI tree to a file.
>  
> Here's my problem:
>  
> I bring up the Python platform with the initial screen GUI.  I run my
> AT-SPI dump client program.  The dump is beautiful.  I run it again.
> The Python ATK support crashes with errors in the Python log like
> this:
>  
> ** (process:2857): CRITICAL **: get_atkobject_from_servant: assertion
> `ATK_IS_OBJECT(object->gobj)' failed
> ** (process:2857): CRITICAL **:
> impl_accessibility_accessible_get_name: assertion `object != NULL'
> failed
> ** (process:2857): CRITICAL **: get_atkobject_from_servant: assertion
> `ATK_IS_OBJECT(object->gobj)' failed
> ** (process:2857): CRITICAL **:
> impl_accessibility_accessible_get_description: assertion `object !=
> NULL' failed
> ** (process:2857): CRITICAL **: get_atkobject_from_servant: assertion
> `ATK_IS_OBJECT(object->gobj)' failed
> 
> The first time I run the client, my ATK Python support is building the
> ATK nodes on demand.  Those nodes are saved and the second time I run
> the client all the ATK nodes should exist.  And they do.  But
> somewhere in between, the first 12 bytes of memory in some of the ATK
> nodes is getting trashed.  In this case I'm talking about the real ATK
> node, the one pointed to by the papi.atk.AtkObject.
>  
> Here are some odd facts:
>  
> I wrote a routine in Python to run though the entire
> papi.atk.AtkObject tree and dump each node and it's parent (parent
> obtained via ATK call). I dumped the tree before and after the memory
> got trashed. In the before dump, every node's parent displays.  In the
> after dump, the leaf nodes cannot find their parent as a result of
> memory being trashed.  But interior nodes are ok.
>  
> To make ATK do stuff, my Python program must call a Papi routine
> (papi.atk.iterate()) over and over in the main GUI loop.  I put some
> checking code around this call examining one particular node which I
> knew would get trashed.  Before one iteration step the node is fine,
> afterwards, the node is trashed.  Is there any way I can figure out
> what action was performed by that iteration step?
>  
> Does this describe a situation familiar to anyone?  It has some
> symptoms of garbage collection, as if the leaf ATK nodes don't have
> the proper ref count.  But the "fact" that the memory seems to be
> trashed by an iteration of ATK main loop doesn't seem consistent with
> garbage collection.
>  
> Any suggestions would be appreciated.
>  
> -Sam
>  
>  
>  
>  
>  
> _______________________________________________
> Gnome-accessibility-devel mailing list
> Gnome-accessibility-devel gnome org
> http://mail.gnome.org/mailman/listinfo/gnome-accessibility-devel



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]