5

I have a small application that generates three different template documents in OOo Writer. When one of the three "generate" buttons is clicked, this is part of the code that is executed (in C#):

// Connect to OOo
if (componentContext == null)
    componentContext = uno.util.Bootstrap.bootstrap();
XMultiServiceFactory multiServiceFactory =
    (XMultiServiceFactory) componentContext.getServiceManager();
XComponentLoader loader = (XComponentLoader)
    multiServiceFactory.createInstance
        ("com.sun.star.frame.Desktop");

// Initialize class members document, text, and cursor
document = (XTextDocument) loader.loadComponentFromURL
    ("private:factory/swriter", "_blank", 0,
     new PropertyValue[0]);
text = document.getText();
cursor = text.createTextCursor();

The following steps cause a crash:

  1. The user generates a document.
  2. The user closes the document (closing OOo).
  3. The user tries to generate another document.

This exception is thrown:

unoidl.com.sun.star.lang.DisposedException: URP-Bridge: disposed(tid=4) Unexpected connection closure

How do I check to make sure the connection is still open before trying to generate another chart? And how do I reconnect if it has been closed?

Edit: More specifically, this is the complete error message:

Marshaling clicked signal
Exception in Gtk# callback delegate
  Note: Applications can use GLib.ExceptionManager.UnhandledException to handle the exception.
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> unoidl.com.sun.star.lang.DisposedException: URP-Bridge: disposed(tid=4) Unexpected connection closure
  at com.sun.star.bridges.mono_uno.UnoInterfaceProxy.ConstructReturnMessage (Any result, System.Object[] args, uno.Typelib.InterfaceMethodTypeDescription* methodTD, IMethodCallMessage callmsg, Any exception) [0x00000] 
  at com.sun.star.bridges.mono_uno.UnoInterfaceProxy.Invoke (IMessage request) [0x00000] 
  at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke (System.Runtime.Remoting.Proxies.RealProxy rp, IMessage msg, System.Exception& exc, System.Object[]& out_args) [0x00000] 
  --- End of inner exception stack trace ---
  at System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00000] 
  at System.Reflection.MethodBase.Invoke (System.Object obj, System.Object[] parameters) [0x00000] 
  at System.Delegate.DynamicInvokeImpl (System.Object[] args) [0x00000] 
  at System.MulticastDelegate.DynamicInvokeImpl (System.Object[] args) [0x00000] 
  at System.Delegate.DynamicInvoke (System.Object[] args) [0x00000] 
  at GLib.Signal.ClosureInvokedCB (System.Object o, GLib.ClosureInvokedArgs args) [0x00000] 
  at GLib.SignalClosure.Invoke (GLib.ClosureInvokedArgs args) [0x00000] 
  at GLib.SignalClosure.MarshalCallback (IntPtr raw_closure, IntPtr return_val, UInt32 n_param_vals, IntPtr param_values, IntPtr invocation_hint, IntPtr marshal_data) [0x00000] 
   at GLib.ExceptionManager.RaiseUnhandledException(System.Exception e, Boolean is_terminal)
   at GLib.SignalClosure.MarshalCallback(IntPtr raw_closure, IntPtr return_val, UInt32 n_param_vals, IntPtr param_values, IntPtr invocation_hint, IntPtr marshal_data)
   at Gtk.Application.gtk_main()
   at Gtk.Application.Run()
   at TestDrive.MainClass.Main(System.String[] args) in /home/matthew/Dropbox/OpenSBS-mono/TestDrive/Main.cs:line 28

The application was terminated by a signal: SIGHUP

If I get rid of the line if (componentContext == null) (i.e., always try to connect, even when we have already connected), I get a stacktrace accompanied by this message:

=================================================================
Got a SIGSEGV while executing native code. This usually indicates
a fatal error in the mono runtime or one of the native libraries 
used by your application.
=================================================================
Matthew
  • 28,056
  • 26
  • 104
  • 170
  • I'm having this same problem. Did you manage to come up with a solution or workaround by any chance? – Dan Stevens Mar 14 '13 at 11:08
  • @Doomy: My memory is a bit foggy, but I believe this (ugly) workaround worked: I created a separate executable that launches OOo and interacts with it as necessary. Every time I need to interact with OOo, I invoke this helper executable from my main program (passing it whatever arguments it requires). Because I only ever open OOo once within one invocation of the helper executable, I can avoid this bug. – Matthew Mar 14 '13 at 18:26
  • Thanks for the response. My workaround was to install the OpenOffice Quickstarter feature and make sure it's running before I run my application. – Dan Stevens Mar 15 '13 at 14:07

2 Answers2

2

I have discovered that this bug doesn't occur if the OpenOffice Quickstarter application is running (located at C:\Program Files (x86)\OpenOffice.org 3\program\quickstart.exe). quickstart.exe appears to call soffice.exe, and it will remaining running even after the user closes the last document window.

If quickstart.exe is missing, it can be installed via the OpenOffice setup program. Your application can make sure that soffice.exe is running by launchingquickstart.exe using the System.Diagnostics.Process.Start(). It won't duplicate the process if it is already running.

Dan Stevens
  • 6,392
  • 10
  • 49
  • 68
2

This is just a guess. You could use XComponent.addEventListener and listen for the disposing event.

eg:

class App :  XEventListener
{
    private XComponentLoader m_loader;

    private XComponentLoader Loader
    {
        get
        {
            if (m_loader == null)
            {
                m_loader = (XComponentLoader)multiServiceFactory.createInstance("com.sun.star.frame.Desktop");
                XComponent comp = (XComponent)m_loader;
                comp.addEventListener(this);
            }
            return m_loader;
        }
    }

    private void disposing(EventObject Source)
    {
        m_loader = null;
    }
}
Foole
  • 4,754
  • 1
  • 26
  • 23
  • This doesn't seem to work. I get my error on the line when getting the multiServiceFactory, not when getting the loader, but changing your code to adjust for this doesn't seem to help. One interesting thing is that "disposing" doesn't seem to get called for the componentContext, multiServiceFactory, or loader when I close OOo. Only the document calls disposing (and trying to reconnect still gives me the error). Perhaps what's happening is that the connection is never fully closed, and that's what makes bootstrap give the error. Any ideas? – Matthew Nov 21 '09 at 17:49