Skip to content

Commit

Permalink
Attempt to remove all gdk threads_enter and leave calls
Browse files Browse the repository at this point in the history
  • Loading branch information
TomasKorbar committed Feb 4, 2019
1 parent e58d4c9 commit 20a3eb9
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 58 deletions.
109 changes: 51 additions & 58 deletions system-config-printer.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,8 @@

# config is generated from config.py.in by configure
import config

import sys, os, time, re
import _thread
import threading
import dbus
import gi
try:
Expand Down Expand Up @@ -94,6 +93,7 @@ def show_help():
import newprinter
from newprinter import busy, ready
import printerproperties
from thread_operations import thread_safe_blocking_call, SCP_MAIN_THREAD_NAME

import ppdippstr
ppdippstr.init ()
Expand Down Expand Up @@ -749,6 +749,7 @@ def on_server_settings_activate (self, menuitem):
except RuntimeError:
self.monitor.update ()

@thread_safe_blocking_call
def setConnected(self):
connected = bool(self.cups)

Expand Down Expand Up @@ -830,6 +831,7 @@ def getServers(self):
known_servers.sort()
return known_servers

@thread_safe_blocking_call
def populateList(self, prompt_allowed=True):
# Save selection of printers.
selected_printers = set()
Expand Down Expand Up @@ -1178,19 +1180,18 @@ def on_connect_activate(self, widget):
cups.setUser('')
self.connect_user = cups.getUser()
# Now start a new thread for connection.
self.connect_thread = _thread.start_new_thread(self.connect,
(self.PrintersWindow,))
self.connect_thread = threading.Thread(target=self.connect,
args=(self.PrintersWindow),
name="SCP_CONNECTING_THREAD"
)
self.connect_thread.start()

def update_connecting_pbar (self):
ret = True
Gdk.threads_enter ()
try:
if not self.ConnectingDialog.get_property ("visible"):
ret = False # stop animation
else:
self.pbarConnecting.pulse ()
finally:
Gdk.threads_leave ()
if not self.ConnectingDialog.get_property ("visible"):
ret = False # stop animation
else:
self.pbarConnecting.pulse ()

return ret

Expand Down Expand Up @@ -1236,38 +1237,40 @@ def connect(self, parent=None):
host=self.connect_server,
encryption=self.connect_encrypt)
except RuntimeError as s:
if self.connect_thread != _thread.get_ident(): return
Gdk.threads_enter()
try:
self.ConnectingDialog.hide()
self.cups = None
self.setConnected()
self.populateList()
show_IPP_Error(None, s, parent)
finally:
Gdk.threads_leave()
if self.connect_thread != threading.currentThread(): return
Gdk.threads_add_idle(GLib.PRIORITY_DEFAULT_IDLE,
self.ConnectingDialog.hide,
)
self.cups = None
self.setConnected()
self.populateList()
Gdk.threads_add_idle(GLib.PRIORITY_DEFAULT_IDLE,
show_IPP_Error,
(None, s, parent)
)
return
except cups.IPPError as e:
(e, s) = e.args
if self.connect_thread != _thread.get_ident(): return
Gdk.threads_enter()
try:
self.ConnectingDialog.hide()
self.cups = None
self.setConnected()
self.populateList()
show_IPP_Error(e, s, parent)
finally:
Gdk.threads_leave()
if self.connect_thread != threading.currentThread(): return
Gdk.threads_add_idle(GLib.PRIORITY_DEFAULT_IDLE,
self.ConnectingDialog.hide,
)
self.cups = None
self.setConnected()
self.populateList()
Gdk.threads_add_idle(GLib.PRIORITY_DEFAULT_IDLE,
show_IPP_Error,
(None, s, parent)
)
return
except:
nonfatalException ()

if self.connect_thread != _thread.get_ident(): return
Gdk.threads_enter()

if self.connect_thread != threading.currentThread(): return
try:
self.ConnectingDialog.hide()
Gdk.threads_add_idle(GLib.PRIORITY_DEFAULT_IDLE,
self.ConnectingDialog.hide,
)
self.cups = connection
self.setConnected()
self.populateList()
Expand All @@ -1276,12 +1279,13 @@ def connect(self, parent=None):
self.cups = None
self.setConnected()
self.populateList()
show_HTTP_Error(s, parent)
Gdk.threads_add_idle(GLib.PRIORITY_DEFAULT_IDLE,
show_HTTP_Error,
(s, parent)
)
except:
nonfatalException ()

Gdk.threads_leave()

def reconnect (self):
"""Reconnect to CUPS after the server has reloaded."""
# libcups would handle the reconnection if we just told it to
Expand Down Expand Up @@ -2058,23 +2062,18 @@ def on_start_service_reply (self, *args):
GLib.timeout_add_seconds (1, self.service_started_try)

def service_started_try (self):
Gdk.threads_enter ()
try:
self.on_btnRefresh_clicked (None)
finally:
Gdk.threads_leave ()
Gdk.threads_add_idle(GLib.PRIORITY_DEFAULT_IDLE,
self.on_btnRefresh_clicked
)


GLib.timeout_add_seconds (1, self.service_started_retry)
return False

def service_started_retry (self):
if not self.cups:
Gdk.threads_enter ()
try:
self.on_btnRefresh_clicked (None)
self.btnStartService.set_sensitive (True)
finally:
Gdk.threads_leave ()

return False

Expand Down Expand Up @@ -2180,11 +2179,7 @@ def on_printer_modified (self, obj, name, ppd_has_changed):
def defer_refresh (self):
def deferred_refresh ():
self.populateList_timer = None
Gdk.threads_enter ()
try:
self.populateList (prompt_allowed=False)
finally:
Gdk.threads_leave ()
self.populateList (prompt_allowed=False)
return False

if self.populateList_timer:
Expand Down Expand Up @@ -2222,6 +2217,8 @@ def cups_connection_recovered (self, mon):

def main(show_jobs):
cups.setUser (os.environ.get ("CUPS_USER", cups.getUser()))
# set name for main thread
threading.currentThread().setName(SCP_MAIN_THREAD_NAME)
Gdk.threads_init ()
from dbus.glib import DBusGMainLoop
DBusGMainLoop (set_as_default=True)
Expand All @@ -2233,11 +2230,7 @@ def main(show_jobs):
else:
mainwindow = GUI()

Gdk.threads_enter ()
try:
Gtk.main()
finally:
Gdk.threads_leave ()
Gtk.main()

if __name__ == "__main__":
import getopt
Expand Down
35 changes: 35 additions & 0 deletions thread_operations.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import threading
from gi.repository import Gdk, GLib

SCP_MAIN_THREAD_NAME = "SCP_MAIN_THREAD"

class Blocker():
def __init__(self):
self.block = True

def thread_safe_blocking_call(function):
""" Make function/method thread safe and block until its call is finished
"""

# we need a class instance because python does not support pointers
blocker = Blocker()

def inner_wrapper(*args, **kwargs):
function(*args, **kwargs)
blocker.block = False
return False

def wrapper(*args, **kwargs):
# if this is the main thread then simply return function
if threading.current_thread().name == SCP_MAIN_THREAD_NAME:
return function(*args, **kwargs)
Gdk.threads_add_idle(
GLib.PRIORITY_DEFAULT_IDLE,
inner_wrapper,
*args,
**kwargs
)
while blocker.block:
pass

return wrapper

0 comments on commit 20a3eb9

Please sign in to comment.