Chasing misc. a11y issues:



Is Bill's work in cvs. ?

(gdb) bt
#0  0x423fbc62 in g_log () from /opt/gnome/lib/libglib-2.0.so.0
#1  0x4232415d in atk_object_get_role (accessible=Variable "accessible" is not available.
) at atkobject.c:714
#2  0x42824ff3 in gail_toplevel_show_event_watcher (ihint=0xbfffe538, n_param_values=1, param_values=0xbfffe650, data=0x80f0d80)
    at gailtoplevel.c:252

(gdb) t 3
[Switching to thread 3 (Thread 16386 (LWP 20348))]#0  0x414992a4 in __pthread_sigsuspend (set=0x414a0484)
    at ../linuxthreads/sysdeps/unix/sysv/linux/pt-sigsuspend.c:54
54        INTERNAL_SYSCALL (rt_sigsuspend, err, 2, set, _NSIG / 8);
(gdb) bt
#0  0x414992a4 in __pthread_sigsuspend (set=0x414a0484) at ../linuxthreads/sysdeps/unix/sysv/linux/pt-sigsuspend.c:54
#1  0x41498028 in __pthread_wait_for_restart_signal (self=0xbf7ffbe0) at pthread.c:1216
#2  0x4149580c in __pthread_cond_wait (cond=Variable "cond" is not available.
) at restart.h:34
#3  0x4296be19 in giop_recv_buffer_get () from /opt/gnome/lib/libORBit-2.so.0
#4  0x42970962 in ORBit_small_invoke_stub () from /opt/gnome/lib/libORBit-2.so.0
#5  0x42970b00 in ORBit_small_invoke_stub_n () from /opt/gnome/lib/libORBit-2.so.0
#6  0x4297d982 in ORBit_c_stub_invoke () from /opt/gnome/lib/libORBit-2.so.0
#7  0x428c048c in Accessibility_EventListener_notifyEvent (_obj=0x81170c8, e=0xfffffffc, ev=0x428405d8) at Accessibility-stubs.c:754
#8  0x4283d72c in spi_atk_emit_eventv (gobject=Variable "gobject" is not available.
) at bridge.c:654
#9  0x4283dc9e in spi_atk_bridge_signal_listener (signal_hint=Variable "signal_hint" is not available.
) at bridge.c:1034
#10 0x423a8ec6 in signal_emit_unlocked_R () from /opt/gnome/lib/libgobject-2.0.so.0
#11 0x423aa371 in g_signal_emit_valist () from /opt/gnome/lib/libgobject-2.0.so.0
#12 0x423aa575 in g_signal_emit_by_name () from /opt/gnome/lib/libgobject-2.0.so.0
#13 0x41f683dc in AtkListener::handleChildRemoved (this=0x939ddf0, rxParent=@0xbf7ff404, rxChild=@0xbf7ff3f4)
    at /opt/OpenOffice/src680-m137/vcl/unx/gtk/a11y/atklistener.cxx:184
#14 0x41f6862f in AtkListener::notifyEvent (this=0x939ddf0, aEvent=@0xbf7ff524)
    at /opt/OpenOffice/src680-m137/vcl/unx/gtk/a11y/atklistener.cxx:226
#15 0x40cbd2f8 in comphelper::AccessibleEventNotifier::addEvent () from ./libcomphelp4gcc3.so
#16 0x40cab7d3 in comphelper::OAccessibleContextHelper::NotifyAccessibleEvent () from ./libcomphelp4gcc3.so
#17 0x411b009a in VCLXAccessibleComponent::ProcessWindowEvent () from ./libtk680li.so
#18 0x411af885 in VCLXAccessibleComponent::WindowEventListener () from ./libtk680li.so
#19 0x411af814 in VCLXAccessibleComponent::LinkStubWindowEventListener () from ./libtk680li.so
#20 0x401e0e34 in Link::Call (this=0x542d90c0, pCaller=0xbf7ff6e4) at link.hxx:155
#21 0x401f81dc in VclEventListeners::Call (this=0x939e360, pEvent=0xbf7ff6e4) at /opt/OpenOffice/src680-m137/vcl/source/app/vclevent.cxx:49
#22 0x403f74a7 in Window::CallEventListeners (this=0x939e198, nEvent=501, pData=0x939d890)
    at /opt/OpenOffice/src680-m137/vcl/source/window/window.cxx:5286
#23 0x403f73eb in Window::ImplCallEventListeners (this=0x939e198, nEvent=501, pData=0x939d890)
    at /opt/OpenOffice/src680-m137/vcl/source/window/window.cxx:5267
#24 0x403f2e0c in ~Window (this=0x939d890) at /opt/OpenOffice/src680-m137/vcl/source/window/window.cxx:4311
#25 0x40421f5c in ~Control (this=0x939d890) at /opt/OpenOffice/src680-m137/vcl/source/control/ctrl.cxx:109
#26 0x4041266f in ~Button (this=0x939d890) at /opt/OpenOffice/src680-m137/vcl/source/control/button.cxx:187
#27 0x4041771f in ~PushButton (this=0x939d890) at /opt/OpenOffice/src680-m137/vcl/source/control/button.cxx:1508
#28 0x40420de3 in ~ImageButton (this=0x939d890) at /opt/OpenOffice/src680-m137/vcl/source/control/button.cxx:4078
#29 0x407f866b in svt::CloserButton_Impl::~CloserButton_Impl () from ./libsvt680li.so
#30 0x407f82de in svt::HelpAgentWindow::~HelpAgentWindow () from ./libsvt680li.so
#31 0x510bc49f in framework::HelpAgentDispatcher::closeAgentWindow () from /opt/OOInstall/program/./libfwk680li.so
#32 0x510bc23d in framework::HelpAgentDispatcher::timerExpired () from /opt/OOInstall/program/./libfwk680li.so
#33 0x510eeab2 in framework::OTimerHelper::onShot () from /opt/OOInstall/program/./libfwk680li.so
#34 0x40dd897d in vos::OTimerManager::checkForTimeout () from ./libvos3gcc3.so
#35 0x40dd8ab6 in vos::OTimerManager::run () from ./libvos3gcc3.so
#36 0x40dd6702 in vos::_cpp_OThread_WorkerFunction () from ./libvos3gcc3.so
#37 0x40dd66e9 in _OThread_WorkerFunction () from ./libvos3gcc3.so
#38 0x40e8e8a0 in osl_thread_start_Impl () from ./libuno_sal.so.3
#39 0x4149628b in pthread_start_thread (arg=Variable "arg" is not available.
) at manager.c:310
#40 0x4149631f in pthread_start_thread_event (arg=0xbf7ffbe0) at manager.c:334
#41 0x4173f55a in clone () from /lib/libc.so.6

vs.

(gdb) t 1
[Switching to thread 1 (Thread 16384 (LWP 20328))]#0  0x414992a4 in __pthread_sigsuspend (set=0x414a0484)
    at ../linuxthreads/sysdeps/unix/sysv/linux/pt-sigsuspend.c:54
54        INTERNAL_SYSCALL (rt_sigsuspend, err, 2, set, _NSIG / 8);
(gdb) bt
#0  0x414992a4 in __pthread_sigsuspend (set=0x414a0484) at ../linuxthreads/sysdeps/unix/sysv/linux/pt-sigsuspend.c:54
#1  0x41498028 in __pthread_wait_for_restart_signal (self=0x4149fbc0) at pthread.c:1216
#2  0x4149b4fc in __pthread_lock (lock=Variable "lock" is not available.
) at restart.h:34
#3  0x414977c5 in *__GI___pthread_mutex_lock (mutex=Variable "mutex" is not available.
) at mutex.c:112
#4  0x40e8df36 in osl_acquireMutex () from ./libuno_sal.so.3
#5  0x40dd199a in vos::OMutex::acquire () from ./libvos3gcc3.so
#6  0x424ea6a6 in SalYieldMutex::acquire (this=0x80a9040) at /opt/OpenOffice/src680-m137/vcl/unx/source/app/salinst.cxx:93
#7  0x41f4a981 in GtkHookedYieldMutex::acquire (this=0x80a9040) at /opt/OpenOffice/src680-m137/vcl/unx/gtk/app/gtkinst.cxx:91
#8  0x424eac65 in X11SalInstance::AcquireYieldMutex (this=0x80a8f58, nCount=1)
    at /opt/OpenOffice/src680-m137/vcl/unx/source/app/salinst.cxx:284
#9  0x41f4a3ad in ~YieldMutexReleaser (this=0xbfffe930) at saldata.hxx:153
#10 0x41f49522 in GtkXLib::Yield (this=0x80a9108, bWait=1 '\001') at /opt/OpenOffice/src680-m137/vcl/unx/gtk/app/gtkdata.cxx:687
#11 0x424eaca9 in X11SalInstance::Yield (this=0x80a8f58, bWait=1 '\001') at /opt/OpenOffice/src680-m137/vcl/unx/source/app/salinst.cxx:290
#12 0x401eac50 in Application::Yield () at /opt/OpenOffice/src680-m137/vcl/source/app/svapp.cxx:539
#13 0x401eab41 in Application::Execute () at /opt/OpenOffice/src680-m137/vcl/source/app/svapp.cxx:501
#14 0x0806e0a8 in desktop::Desktop::Main ()
#15 0x401f3510 in ImplSVMain () at /opt/OpenOffice/src680-m137/vcl/source/app/svmain.cxx:242
#16 0x401f361b in SVMain () at /opt/OpenOffice/src680-m137/vcl/source/app/svmain.cxx:273
#17 0x08067971 in sal_main ()
#18 0x0806790c in main ()


** What is happening **

+ we are writing down a socket to the same process & blocking until it returns ...
+ unfortunately - we are also holding the Solar Mutex ..
+ even more unfortunately - the impl. is in the current process & the mainloop is blocked by this.

** Foo ! ... **

+ so ... same problem as idle gnome-vfs init at startup (?) 
    + need to be more intelligent about the 'main' GThread
	+ in this case it is us: we 'own' *world* at this stage.


+ ORBit2/src/orb/orb-core/orbit-small.c:
    + ORBit_small_invoke_stub:
	+ calls ORBit_objref_get_proxy
	    + urgh...

+ What can we do here ?
    + can we 

The problem is perhaps here:

2003-05-29  Michael Meeks  <michael@ximian.com>

        * src/orb/orb-core/orbit-small.c
        (ORBit_small_invoke_stub): check cross-thread calls,
        and generate an in-proc proxy for non-allowed xt cases.

        * src/orb/poa/poa.c (ORBit_poa_allow_cross_thread_call): impl.
        (get_c_method): use it.

        * src/orb/GIOP/giop.c (giop_thread_same_key): impl.

** Same as the VFS problem:

=> ORB initialization ...
    + assuming we initialize the ORB 1st ...
	+ that -does- store a 'primary thread' concept.

    + giop.c (giop_init)
	+ sets 'giop_main_thread' to be the one with the
	  g_main_context_default() association;
	+ sets that thread's thread data to be that ...

    ** Instead **
	+ we need to implement 'g_main_context_is_owner' [ or sim. ]

=> Test:
    ** Need an idle timeout in 1 thread (same [default] mainloop)
       to be locked by another thread etc.

	+ a condition to fire ?
	+ spawn another thread ?

=> Is there a 'default' mainloop ? - does gtk+ assume this ?
    + Yes a default context: "g_main_context_default ()"
    + can we assume it to slave ORBit2 locking from it ?

    + g_main_context_acquire / release
	+ closest equivalent to recursive Solar Mutex ...

    'bool IsMainThread'
	+ if (g_main_context_acquire (NULL))
	  {
	    g_main_context_release (NULL); return TRUE;
	  }
	else return FALSE;

    + etc.

	+ Would - a) check not in I/O thread
	          b) try to grab glib lock to process in-line ?
	  work ?

	+ ST gtk+ apps - biggest concern ...
		+ non-issue; this won't occur.

	+ in our 'client' case:
		+ call 'stub-invoke' from N threads
		+ goes to I/O thread ...
		+ then what ?
			+ no 'glib' thread anyway,
			+ => who should process this ?

	+ whomever is 1st - process in-thread ?
		+ but - if we don't spin the mainloop ...
			+ what happens !?

	+ can we / should we rely on someone running a
	  (default) glib mainloop somewhere ?
		+ [ prolly yes ... ]

	+ The real problem is one of deadlock.
		+ 2 'locks'
			+ g_main_context - to process a request
			+ gdk_threads - to use gtk+

	+ To determine whether to invoke XYZ in-process
	  via fake I/O
		+ need to know if it's possible to process it:
			+ if we can get the g_main_context it is not.
			=> certain that we would block otherwise ?
			=> are we certain that we will deadlock though ?

	+ What about a thread -> I/O to the I/O thread -> but there is no glib mainloop ?

	+ Should we then just do it in-process in the thread ?
		+ if not, 

	+ can we special case 'unrefs' ?
		+ ... urgh ...
		+ can we 'g_idle_add (foo, unref)'

	+ URGH - why don't we just do 'bonobo_object_unref()' ...

	+ foo ...

	+ Can we think of a scenario we would break by doing XYZ ?
		+ when do we spawn the I/O as a separate thread ?
			+ idly ? - when another thread emits a call ...

	+ So - the single-threaded GConf case will still work.
		+ not a problem ...

	+ If we have the 'g_main_context' lock - it is *possible* that
	  we don't have the gdk lock.

	+ what do we break:
		+ the case where thread a) didn't have a glib mainloop,
		+ and thread b) was running it - but not 'in' the loop

	+ g_main_context_acquire/release called top/tail of
		+ g_main_context_iterate ...
		+ with a g_main_run type thing
			+ we ~always hold the context - if we're doing
			  anything useful.

	+ => only 1 thread can be processing 'stuff' on that glib
	  mainloop concurrently.

	+ this is the behavior we want.
		+ not 'thread affine' but 'context affine'

	+ If we hold the Solar mutex to do stuff - the more the merrier.

** Problem:
	+ what about multiple slave threads - only 1 can get the context
		+ but this thread will not process any calls but it's
		  own (probably)
		+ [ in this case - should we spin the glib mainloop a bit ?
** NO:		    *Evil* re-enterancy hazard ... ]

	+ => all these threads need to wait for the main context (?)
		+ [ the I/O thread will do the I/O for us prolly ]
		+ 

	+ So - use g_main_context_wait (context, cont, mutex)
		+ [ this will kick the main-loop & not be a problem ]
		+ [ possibly we also need a 'wakeup' before that ]

	+ moral - your STA shouldn't run the default glib mainloop ? ;->
		+ *OR* your 'other' thread, shouldn't run the default glib mainloop ?
		+ thread-affine gtk+ mainloop in VCL ?

	+ Can we then process the request in-process -if-we-have-that-lock ?
		+ avoids marshalling => also a speedup :-)

	need a:
		+ g_main_really_acquire:
			++ (g_main_context_default())
			while (!g_main_context_wait ()) ;
			... [ call method in-process ] ...
		+ g_main_context_release ();

	* so far:
		+ orbit-policy.c: clean anyway
		+ 
		+ giop.c: fixed.
		+ 

	* ORBit2/src/orb/GIOP/giop.c:
		+ [foo]
		+ give up with this approach - just 'get_main_context'
		  & do it in-line (or emit idly ... [async])

	+ giop_thread_new_check:
		+ the only -legitimiate- use of giop_thread_main
			+ rename to ORB_init_thread
	+ giop_thread_set_main_handler
		+ Needs re-naming to be 'giop_set_incoming_handler'
	+ giop_thread_get_main
		+ needs to die ...
	+ giop_thread_same_key
		+ 1 use in poa.c
	+ giop_thread_self:
		+ dangerous if pushing to a queue eg.

	* ORBit2/src/orb/GIOP/giop-recv-buffer.c:
		+ set src_thread ...
		+ giop_recv_buffer_get - seems sane still.

	* ORBit2/src/orb/orb-core/orbit-policy.c:
		+ clean.

	* ORBit2/src/orb/poa/poa.c:
		+ (ORBit_poa_allow_cross_thread_call)
			+ the main fix necessary is here
			+ the other POA bits - only called from
			  existing I/O that has happened (?)
			  and/or the I/O thread - ie. this problem
			  doesn't apply
			+ thread-same-key bit is fine ...
		+ Other:
			+ (ORBit_POA_handle_request)
				+ requires SINGLE_THREAD re-work ...
			+ ONEWAY_AT_IDLE
				+ also requires re-work.
			+ push_request_T [ take a NULL ? ]
		+ use the right main context foo ...

	* We hurt people who were not running a custom/glib integrated
	  mainloop, and were relying on nothing happening from another
	  thread. c'est-la-vie ...
		+ And were using threads
		+ and were calling 'single threaded' / main appartment
		  calls from them.

	* Linc
		+ seems linc is not thread-affine
		+ except for the I/O thread - fair enough.


* FIXME:
	+ Audit 'main' thread queue & g_main_context wakeup
	  foo ...
		+ need to make sure that whatever giop_get_self
		  returns - we do the work ...
		+ giop_mainloop_handle_input

	+ Do we need a per-thread 'tdata' - for 'is this the main thread'
		+ and also a 'giop_gmain_pseudo_thread' (?)
		+ how will this work for single-threaded case ?

	+ How does this work with people waiting for data to
	  come back ? [ single threaded etc. ? ... ]
		+ either the main 'thread context' or ... ?
		+ Audit giop_recv_list_setup_queue_entry ...

		+ what is the src_thread used for:
		    + giop.c:
			+ giop_invoke_async
				+ [bogus] - check for same thread
				  to emit async callback - needs
				  be 'get_main_appartment_foo' etc. (?)
				+ should instead try to get maincontext ?
				+ should check 'are-we-in-IO-thread?'
					+ if so ... XYZ
			+ else - signal a thread-pool-thread ...
				+ push on/off stack etc. [urgh]

			+ [perhaps detecting foo .. ]
		    + giop-recv-buffer.c
			+ ent_lock / ent_unlock ...
			+ giop_recv_list_zap
				+ giop_incoming_signal_T ...

	+ Some problem:
		+ some non-main-loop async callback functionality
		  not expected...
			+ can get an async callback from an idling
			  method / the inferior mainloop - possibly
			  useful.

	+ How do we know which queue to put it on ?
**NO:	    + For async:
		+ if (no-thread-io)
			=> use main/default context queue.
		  else if (safe_get_main_context)
			=> use main as before
			unlock ...
		  else if (random other)
			set src_thread to current value.

	** Unfortunately
		+ we can accidentally get the glib context
		  'by mistake' ... in a random thread.

	** What are we trying to achieve ?
		+ can we push this back ?
		+ who knows what thread we are really in ?
			+ same async API used for both
			  'call-back-in-this-thread'
			+ and 'call-back-in-main-loop'
		+ Not possible to distinguish in the ORB.
			+ Ergo - we have to make all async
			  calls return in the GMainContext
			+ our only hope ...
		+ of course all returns go to the waiting
		  XYZ thread ...

	** we want to 'take/grab/poke' the GMainContext lock
		+ no way to do that
		+ can't push into the mainloop -> may not be running.
		+ we can require that there is a running loop for that
		  case.
			+ different past ?
			+ have a glib mainloop running ?
				+ ask for the context
				+ if we can't get it push ...
				+ but don't allow re-enterancy.
			+ => foo ...
			+ make tests spin...

	** Did we break anything else ? **
	    ... re-enterancy ...
		+ This also fixes the ORBit2 foo ...
		+ What async invocation stuff do we need
		  for a11y ? ...

	** poa's: thread_push_T
	    + is this ok ?

** 2 problems
    + a) handle_request - have no idea who to hand
         it to / wake-up on 'NULL'
	    + which of the waiting threads is the 'main' one ...
    + as we acquire / release the context over a call
      - we can find out ?
    + b) Handle incoming foo [!?] - no idea what queue to put it on ...
	+ should we have a 'set this as main thread' ?
	    + whomever is waiting & has the lock ?
	    + have no 'main thread' thing; but switch ownership ?
	      + rotate & leave 'the main thread' as the owner
	      + have a lock on it (?)
      + a g_idle_foo - that sets us as the owner ?
      + 

	** "We get a 'handle_reqest'
	    + no idea to whom to hand it ...
	    + no way of knowing if we 'own' the glib mainloop
	      reliably ...
	** if g_get_foo ...
	** then ...

TODO:
    ** Audit 'handle_reply' pointer changes in diff:
    



** Other approaches:
    + just don't do any CORBA IPC in-proc to other objects
	++ OR - tag them all as 'thread-safe' though they are not...

** Perhaps unify thread foo ..
    + 
