]> sourceware.org Git - lvm2.git/commitdiff
lvmdbusd: Fix hang for Job.Wait(n)
authorTony Asleson <tasleson@redhat.com>
Wed, 27 Jul 2016 23:27:58 +0000 (18:27 -0500)
committerTony Asleson <tasleson@redhat.com>
Thu, 28 Jul 2016 16:13:29 +0000 (11:13 -0500)
When a client is doing a wait on a job, any other clients will hang
when trying to do anything with the service.  This is caused by
the wait code which  was placing the thread that handles
incoming dbus requests to sleep until either the timeout expired or
the job operation completed.

This change creates a thread for the wait request, so that the thread
processing incoming requests can continue to run.

daemons/lvmdbusd/background.py
daemons/lvmdbusd/job.py

index 2c719fca93ff8d3ef94b29901113ba731ce47994..8078b662973d5b2ee1b5862b5f5e3d51cb4614e4 100644 (file)
@@ -13,7 +13,7 @@ from . import cfg
 import time
 from .cmdhandler import options_to_cli_args
 import dbus
-from .utils import pv_range_append, pv_dest_ranges, log_error
+from .utils import pv_range_append, pv_dest_ranges, log_error, log_debug
 import traceback
 
 _rlock = threading.RLock()
@@ -118,6 +118,7 @@ def background_reaper():
                                for i in range(num_threads, -1, -1):
                                        _thread_list[i].join(0)
                                        if not _thread_list[i].is_alive():
+                                               log_debug("Removing thread: %s" % _thread_list[i].name)
                                                _thread_list.pop(i)
 
                time.sleep(3)
@@ -171,3 +172,30 @@ def add(command, reporting_job):
 
        with _rlock:
                _thread_list.append(t)
+
+
+def wait_thread(job, timeout, cb, cbe):
+       # We need to put the wait on it's own thread, so that we don't block the
+       # entire dbus queue processing thread
+       try:
+               cb(job.state.Wait(timeout))
+       except Exception as e:
+               cbe("Wait exception: %s" % str(e))
+       return 0
+
+
+def add_wait(job, timeout, cb, cbe):
+
+       if timeout == 0:
+               # Users are basically polling, do not create thread
+               cb(job.Complete)
+       else:
+               t = threading.Thread(
+                       target=wait_thread,
+                       name="thread job.Wait: %s" % job.dbus_object_path(),
+                       args=(job, timeout, cb, cbe)
+               )
+
+               t.start()
+               with _rlock:
+                       _thread_list.append(t)
index d7f8187e5430d8df9a1303a0645b1567bf09983a..520f9a87e5c477467993d4fadc2ccf21004d655a 100644 (file)
@@ -13,6 +13,7 @@ from . import cfg
 from .cfg import JOB_INTERFACE
 import dbus
 import threading
+from . import background
 
 
 # noinspection PyPep8Naming
@@ -152,9 +153,10 @@ class Job(AutomatedProperties):
 
        @dbus.service.method(dbus_interface=JOB_INTERFACE,
                                                        in_signature='i',
-                                                       out_signature='b')
-       def Wait(self, timeout):
-               return self.state.Wait(timeout)
+                                                       out_signature='b',
+                                                       async_callbacks=('cb', 'cbe'))
+       def Wait(self, timeout, cb, cbe):
+               background.add_wait(self, timeout, cb, cbe)
 
        @property
        def Result(self):
This page took 0.043943 seconds and 5 git commands to generate.