Skip to content

Commit 20a3eb9

Browse files
committed
Attempt to remove all gdk threads_enter and leave calls
1 parent e58d4c9 commit 20a3eb9

File tree

2 files changed

+86
-58
lines changed

2 files changed

+86
-58
lines changed

system-config-printer.py

Lines changed: 51 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,8 @@
2323

2424
# config is generated from config.py.in by configure
2525
import config
26-
2726
import sys, os, time, re
28-
import _thread
27+
import threading
2928
import dbus
3029
import gi
3130
try:
@@ -94,6 +93,7 @@ def show_help():
9493
import newprinter
9594
from newprinter import busy, ready
9695
import printerproperties
96+
from thread_operations import thread_safe_blocking_call, SCP_MAIN_THREAD_NAME
9797

9898
import ppdippstr
9999
ppdippstr.init ()
@@ -749,6 +749,7 @@ def on_server_settings_activate (self, menuitem):
749749
except RuntimeError:
750750
self.monitor.update ()
751751

752+
@thread_safe_blocking_call
752753
def setConnected(self):
753754
connected = bool(self.cups)
754755

@@ -830,6 +831,7 @@ def getServers(self):
830831
known_servers.sort()
831832
return known_servers
832833

834+
@thread_safe_blocking_call
833835
def populateList(self, prompt_allowed=True):
834836
# Save selection of printers.
835837
selected_printers = set()
@@ -1178,19 +1180,18 @@ def on_connect_activate(self, widget):
11781180
cups.setUser('')
11791181
self.connect_user = cups.getUser()
11801182
# Now start a new thread for connection.
1181-
self.connect_thread = _thread.start_new_thread(self.connect,
1182-
(self.PrintersWindow,))
1183+
self.connect_thread = threading.Thread(target=self.connect,
1184+
args=(self.PrintersWindow),
1185+
name="SCP_CONNECTING_THREAD"
1186+
)
1187+
self.connect_thread.start()
11831188

11841189
def update_connecting_pbar (self):
11851190
ret = True
1186-
Gdk.threads_enter ()
1187-
try:
1188-
if not self.ConnectingDialog.get_property ("visible"):
1189-
ret = False # stop animation
1190-
else:
1191-
self.pbarConnecting.pulse ()
1192-
finally:
1193-
Gdk.threads_leave ()
1191+
if not self.ConnectingDialog.get_property ("visible"):
1192+
ret = False # stop animation
1193+
else:
1194+
self.pbarConnecting.pulse ()
11941195

11951196
return ret
11961197

@@ -1236,38 +1237,40 @@ def connect(self, parent=None):
12361237
host=self.connect_server,
12371238
encryption=self.connect_encrypt)
12381239
except RuntimeError as s:
1239-
if self.connect_thread != _thread.get_ident(): return
1240-
Gdk.threads_enter()
1241-
try:
1242-
self.ConnectingDialog.hide()
1243-
self.cups = None
1244-
self.setConnected()
1245-
self.populateList()
1246-
show_IPP_Error(None, s, parent)
1247-
finally:
1248-
Gdk.threads_leave()
1240+
if self.connect_thread != threading.currentThread(): return
1241+
Gdk.threads_add_idle(GLib.PRIORITY_DEFAULT_IDLE,
1242+
self.ConnectingDialog.hide,
1243+
)
1244+
self.cups = None
1245+
self.setConnected()
1246+
self.populateList()
1247+
Gdk.threads_add_idle(GLib.PRIORITY_DEFAULT_IDLE,
1248+
show_IPP_Error,
1249+
(None, s, parent)
1250+
)
12491251
return
12501252
except cups.IPPError as e:
12511253
(e, s) = e.args
1252-
if self.connect_thread != _thread.get_ident(): return
1253-
Gdk.threads_enter()
1254-
try:
1255-
self.ConnectingDialog.hide()
1256-
self.cups = None
1257-
self.setConnected()
1258-
self.populateList()
1259-
show_IPP_Error(e, s, parent)
1260-
finally:
1261-
Gdk.threads_leave()
1254+
if self.connect_thread != threading.currentThread(): return
1255+
Gdk.threads_add_idle(GLib.PRIORITY_DEFAULT_IDLE,
1256+
self.ConnectingDialog.hide,
1257+
)
1258+
self.cups = None
1259+
self.setConnected()
1260+
self.populateList()
1261+
Gdk.threads_add_idle(GLib.PRIORITY_DEFAULT_IDLE,
1262+
show_IPP_Error,
1263+
(None, s, parent)
1264+
)
12621265
return
12631266
except:
12641267
nonfatalException ()
12651268

1266-
if self.connect_thread != _thread.get_ident(): return
1267-
Gdk.threads_enter()
1268-
1269+
if self.connect_thread != threading.currentThread(): return
12691270
try:
1270-
self.ConnectingDialog.hide()
1271+
Gdk.threads_add_idle(GLib.PRIORITY_DEFAULT_IDLE,
1272+
self.ConnectingDialog.hide,
1273+
)
12711274
self.cups = connection
12721275
self.setConnected()
12731276
self.populateList()
@@ -1276,12 +1279,13 @@ def connect(self, parent=None):
12761279
self.cups = None
12771280
self.setConnected()
12781281
self.populateList()
1279-
show_HTTP_Error(s, parent)
1282+
Gdk.threads_add_idle(GLib.PRIORITY_DEFAULT_IDLE,
1283+
show_HTTP_Error,
1284+
(s, parent)
1285+
)
12801286
except:
12811287
nonfatalException ()
12821288

1283-
Gdk.threads_leave()
1284-
12851289
def reconnect (self):
12861290
"""Reconnect to CUPS after the server has reloaded."""
12871291
# libcups would handle the reconnection if we just told it to
@@ -2058,23 +2062,18 @@ def on_start_service_reply (self, *args):
20582062
GLib.timeout_add_seconds (1, self.service_started_try)
20592063

20602064
def service_started_try (self):
2061-
Gdk.threads_enter ()
2062-
try:
2063-
self.on_btnRefresh_clicked (None)
2064-
finally:
2065-
Gdk.threads_leave ()
2065+
Gdk.threads_add_idle(GLib.PRIORITY_DEFAULT_IDLE,
2066+
self.on_btnRefresh_clicked
2067+
)
2068+
20662069

20672070
GLib.timeout_add_seconds (1, self.service_started_retry)
20682071
return False
20692072

20702073
def service_started_retry (self):
20712074
if not self.cups:
2072-
Gdk.threads_enter ()
2073-
try:
20742075
self.on_btnRefresh_clicked (None)
20752076
self.btnStartService.set_sensitive (True)
2076-
finally:
2077-
Gdk.threads_leave ()
20782077

20792078
return False
20802079

@@ -2180,11 +2179,7 @@ def on_printer_modified (self, obj, name, ppd_has_changed):
21802179
def defer_refresh (self):
21812180
def deferred_refresh ():
21822181
self.populateList_timer = None
2183-
Gdk.threads_enter ()
2184-
try:
2185-
self.populateList (prompt_allowed=False)
2186-
finally:
2187-
Gdk.threads_leave ()
2182+
self.populateList (prompt_allowed=False)
21882183
return False
21892184

21902185
if self.populateList_timer:
@@ -2222,6 +2217,8 @@ def cups_connection_recovered (self, mon):
22222217

22232218
def main(show_jobs):
22242219
cups.setUser (os.environ.get ("CUPS_USER", cups.getUser()))
2220+
# set name for main thread
2221+
threading.currentThread().setName(SCP_MAIN_THREAD_NAME)
22252222
Gdk.threads_init ()
22262223
from dbus.glib import DBusGMainLoop
22272224
DBusGMainLoop (set_as_default=True)
@@ -2233,11 +2230,7 @@ def main(show_jobs):
22332230
else:
22342231
mainwindow = GUI()
22352232

2236-
Gdk.threads_enter ()
2237-
try:
2238-
Gtk.main()
2239-
finally:
2240-
Gdk.threads_leave ()
2233+
Gtk.main()
22412234

22422235
if __name__ == "__main__":
22432236
import getopt

thread_operations.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import threading
2+
from gi.repository import Gdk, GLib
3+
4+
SCP_MAIN_THREAD_NAME = "SCP_MAIN_THREAD"
5+
6+
class Blocker():
7+
def __init__(self):
8+
self.block = True
9+
10+
def thread_safe_blocking_call(function):
11+
""" Make function/method thread safe and block until its call is finished
12+
"""
13+
14+
# we need a class instance because python does not support pointers
15+
blocker = Blocker()
16+
17+
def inner_wrapper(*args, **kwargs):
18+
function(*args, **kwargs)
19+
blocker.block = False
20+
return False
21+
22+
def wrapper(*args, **kwargs):
23+
# if this is the main thread then simply return function
24+
if threading.current_thread().name == SCP_MAIN_THREAD_NAME:
25+
return function(*args, **kwargs)
26+
Gdk.threads_add_idle(
27+
GLib.PRIORITY_DEFAULT_IDLE,
28+
inner_wrapper,
29+
*args,
30+
**kwargs
31+
)
32+
while blocker.block:
33+
pass
34+
35+
return wrapper

0 commit comments

Comments
 (0)