Bug 58664 - Headless Mode Fails to Shutdown
Summary: Headless Mode Fails to Shutdown
Status: RESOLVED NOTOURBUG
Alias: None
Product: LibreOffice
Classification: Unclassified
Component: LibreOffice (show other bugs)
Version:
(earliest affected)
3.6.4.3 release
Hardware: x86-64 (AMD64) Linux (All)
: medium normal
Assignee: Not Assigned
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-12-22 21:12 UTC by kiaora-paora
Modified: 2013-12-29 13:55 UTC (History)
2 users (show)

See Also:
Crash report or crash signature:


Attachments
python script to demonstrate the problem (5.89 KB, text/x-python)
2012-12-22 21:12 UTC, kiaora-paora
Details
reproducer ported to python3 (5.81 KB, text/x-python)
2013-12-29 11:35 UTC, Riccardo Magliocchetti
Details
reproducer ported to python3 (5.57 KB, text/x-python)
2013-12-29 13:20 UTC, Riccardo Magliocchetti
Details

Note You need to log in before you can comment on or make changes to this bug.
Description kiaora-paora 2012-12-22 21:12:44 UTC
Created attachment 72002 [details]
python script to demonstrate the problem

Problem description:
--------------------

LibreOffice 3.6 running in 'headless' mode does not shutdown when the dispose() method is called on the ComponentContext handle returned by the ServiceManager using the PyUNO bridge under Debian Squeeze.

This appears to be a regression from 3.5.

Steps to reproduce:
-------------------

Save the attached Python script.  This is cut down example from an application that works under 3.5 without issue.

This script is known to work under Debian Squeeze.  Pathnames may need tweaking for other Linux distributions.

Under Debian Squeeze, the script may be invoked from a command line with:

/opt/libreoffice3.5/program/python ./bugHeadless.py

or

/opt/libreoffice3.6/program/python ./bugHeadless.py

The script starts LibreOffice in 'headless' mode and invites the user to verify this using ps(1).  On resume, the shutdown LibreOffice down by calling dispose() and invites the user to verify using ps(1).

Expected behaviour (3.5):
-------------------------

Under LibreOffice 3.5 (currently 3.5.7), LibreOffice is observed to always shutdown with this script.

Current behaviour (3.6):
------------------------

Under LibreOffice 3.6 (currently 3.6.4 but the issue was first noted with 3.6.2), LibreOffice has never been observed to shutdown.

LibreOffice never shuts down with this script.  The script does not manipulate any documents.  With the full application, which does manipulate documents, LibreOffice shuts down.  Usually.

However, on at least two occasions it has not and has slowly eaten all main memory and then all swap until the OOM kills off the desktop itself.
LibreOffice continues to eat memory until the system is totally moribund and a power cycle becomes inevitable.  Not good.

Platform:
--------

  Debian GNU/Linux 6.0.5 (aka Squeeze, aka Stable)

Installation media:

  LibO_3.6.4_Linux_x86-64_helppack-deb_en-GB.tar.gz
  LibO_3.6.4_Linux_x86-64_install-deb_en-US.tar.gz
  LibO_3.6.4_Linux_x86-64_langpack-deb_en-GB.tar.gz
  LibO-SDK_3.6.4_Linux_x86-64_install-deb_en-US.tar.gz
Comment 1 kiaora-paora 2013-03-20 19:10:17 UTC
This issue IS present in LibreOffice 4.0.0.
Comment 2 kiaora-paora 2013-05-13 19:45:22 UTC
This issue IS still present in 4.0.3.
Comment 3 tommy27 2013-12-28 22:49:03 UTC
@Forester
is this issue still present in 4.1.4? 
by the way I put "headless mode" expert to CC list.
Comment 4 Riccardo Magliocchetti 2013-12-29 11:35:22 UTC
Created attachment 91277 [details]
reproducer ported to python3
Comment 5 Riccardo Magliocchetti 2013-12-29 13:20:20 UTC
Created attachment 91286 [details]
reproducer ported to python3

This time one that works
Comment 6 Riccardo Magliocchetti 2013-12-29 13:55:53 UTC
First of all for a more authoritative answer you may want to add someone like sberg. Said that i have a few considerations:

- I don't see much value on starting and killing libreoffice instances on demand, unless it is a requirement i'd advice to let your init system / a process manager handle libo.
 
- Regarding the issue i've never poked with pyuno directly but always used unoconv, this is the relevant bits it is using for killing a libo instance it started:

        ### If there is no GUI attached to the instance, terminate instance
        else:
            info(3, 'Terminating %s instance.' % product.ooName)
            try:
                convertor.desktop.terminate()
            except DisposedException:
                info(2, '%s instance unsuccessfully closed, sending TERM signal.' % product.ooName)
                try:
                    ooproc.terminate()
                except AttributeError:
                    os.kill(ooproc.pid, 15)
            info(3, 'Waiting for %s instance to exit.' % product.ooName)
            ooproc.wait()

where convertor.desktop is:

        ### Do the LibreOffice component dance
        self.context = uno.getComponentContext()
        self.svcmgr = self.context.ServiceManager
        resolver = self.svcmgr.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", self.context)

        unocontext = resolver.resolve("uno:%s" % op.connection)
        unosvcmgr = unocontext.ServiceManager
        self.desktop = unosvcmgr.createInstanceWithContext("com.sun.star.frame.Desktop", unocontext)

and ooproc is:

        ooproc = subprocess.Popen([office.binary, "-headless", "-invisible", "-nocrashreport", "-nodefault", "-nofirststartwizard", "-nologo", "-norestore", "-accept=%s" % op.connection], env=os.environ)

which brings me to this working patch:

--- bugHeadless3.py	2013-12-29 14:17:48.542798672 +0100
+++ bugHeadless3.mod.py	2013-12-29 14:46:29.503332461 +0100
@@ -28,6 +28,7 @@
             try:
                 resolver = local.ServiceManager.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", local)
                 self._officeContext = resolver.resolve("uno:{0};StarOffice.ComponentContext".format(self.unoUrp()))
+                self.desktop = self._officeContext.ServiceManager.createInstanceWithContext("com.sun.star.frame.Desktop", self._officeContext)
             except NoConnectException as e:
                 self.reset()
                 raise Exception("Office not running (?): {0}".format(str(e)))
@@ -118,7 +119,7 @@
         if not self._officeContext is None:
             print("shutdownOffice")
             print(self._officeContext)
-            self._officeContext.dispose()
+            self.desktop.terminate()
             self.reset()
             time.sleep(1)
         return self

So in conclusion it looks to me like an user error. Feel free to dig into unoconv history to see if that was a libo change done during times or just your script used to work by luck. Nobody here is to blame though since the API is horrible.