Skip to content

Commit d9c828e

Browse files
committed
Attempt to remove all gdk threads_enter and leave calls
Changed used module for handling of threads from _thread to threading. Threading has better API and allows us to distinguish threads more easily. However there is a minor problem. When Gdk Window is passed as a argument to method executed in different thread then it is converted before execution of method into Gtk box. That is why i removed parent argument from connect method of GUI class. Parent argument has been removed from connect method of GUI class. Reasons described above. Connect was always called with the same parent anyway so this does not change its function. Added thread_operations.py file. It contains decorator which simulates some functionalities provided by deprecated functions. Some calls of deprecated functions have been replaced by Gdk_threads_add_idle function.
1 parent e58d4c9 commit d9c828e

File tree

3 files changed

+84
-60
lines changed

3 files changed

+84
-60
lines changed

Makefile.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ nobase_pkgdata_DATA= \
130130
smburi.py \
131131
statereason.py \
132132
timedops.py \
133+
thread_operations.py \
133134
ToolbarSearchEntry.py \
134135
userdefault.py \
135136
ui/AboutDialog.ui \

system-config-printer.py

Lines changed: 53 additions & 60 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,17 @@ 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+
name="SCP_CONNECTING_THREAD"
1185+
)
1186+
self.connect_thread.start()
11831187

11841188
def update_connecting_pbar (self):
11851189
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 ()
1190+
if not self.ConnectingDialog.get_property ("visible"):
1191+
ret = False # stop animation
1192+
else:
1193+
self.pbarConnecting.pulse ()
11941194

11951195
return ret
11961196

@@ -1207,7 +1207,7 @@ def on_cancel_connect_clicked(self, widget):
12071207
self.connect_thread = None
12081208
self.ConnectingDialog.hide()
12091209

1210-
def connect(self, parent=None):
1210+
def connect(self):
12111211
"""
12121212
Open a connection to a new server. Is executed in a separate thread!
12131213
"""
@@ -1232,42 +1232,44 @@ def connect(self, parent=None):
12321232
nonfatalException ()
12331233

12341234
try:
1235-
connection = authconn.Connection(parent,
1235+
connection = authconn.Connection(self.PrintersWindow,
12361236
host=self.connect_server,
12371237
encryption=self.connect_encrypt)
12381238
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()
1239+
if self.connect_thread != threading.currentThread(): return
1240+
Gdk.threads_add_idle(GLib.PRIORITY_DEFAULT_IDLE,
1241+
self.ConnectingDialog.hide,
1242+
)
1243+
self.cups = None
1244+
self.setConnected()
1245+
self.populateList()
1246+
Gdk.threads_add_idle(GLib.PRIORITY_DEFAULT_IDLE,
1247+
show_IPP_Error,
1248+
None, s, self.PrintersWindow
1249+
)
12491250
return
12501251
except cups.IPPError as e:
12511252
(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()
1253+
if self.connect_thread != threading.currentThread(): return
1254+
Gdk.threads_add_idle(GLib.PRIORITY_DEFAULT_IDLE,
1255+
self.ConnectingDialog.hide,
1256+
)
1257+
self.cups = None
1258+
self.setConnected()
1259+
self.populateList()
1260+
Gdk.threads_add_idle(GLib.PRIORITY_DEFAULT_IDLE,
1261+
show_IPP_Error,
1262+
None, s, self.PrintersWindow
1263+
)
12621264
return
12631265
except:
12641266
nonfatalException ()
12651267

1266-
if self.connect_thread != _thread.get_ident(): return
1267-
Gdk.threads_enter()
1268-
1268+
if self.connect_thread != threading.currentThread(): return
12691269
try:
1270-
self.ConnectingDialog.hide()
1270+
Gdk.threads_add_idle(GLib.PRIORITY_DEFAULT_IDLE,
1271+
self.ConnectingDialog.hide,
1272+
)
12711273
self.cups = connection
12721274
self.setConnected()
12731275
self.populateList()
@@ -1276,12 +1278,13 @@ def connect(self, parent=None):
12761278
self.cups = None
12771279
self.setConnected()
12781280
self.populateList()
1279-
show_HTTP_Error(s, parent)
1281+
Gdk.threads_add_idle(GLib.PRIORITY_DEFAULT_IDLE,
1282+
show_HTTP_Error,
1283+
s, self.PrintersWindow
1284+
)
12801285
except:
12811286
nonfatalException ()
12821287

1283-
Gdk.threads_leave()
1284-
12851288
def reconnect (self):
12861289
"""Reconnect to CUPS after the server has reloaded."""
12871290
# libcups would handle the reconnection if we just told it to
@@ -2058,23 +2061,19 @@ def on_start_service_reply (self, *args):
20582061
GLib.timeout_add_seconds (1, self.service_started_try)
20592062

20602063
def service_started_try (self):
2061-
Gdk.threads_enter ()
2062-
try:
2063-
self.on_btnRefresh_clicked (None)
2064-
finally:
2065-
Gdk.threads_leave ()
2064+
Gdk.threads_add_idle(GLib.PRIORITY_DEFAULT_IDLE,
2065+
self.on_btnRefresh_clicked,
2066+
None
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: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import threading
2+
gi.require_version('Gdk', '3.0')
3+
from gi.repository import Gdk, GLib
4+
5+
SCP_MAIN_THREAD_NAME = "SCP_MAIN_THREAD"
6+
7+
def thread_safe_blocking_call(function):
8+
""" Make function/method thread safe and block until its call is finished
9+
"""
10+
11+
blocker = threading.Event()
12+
13+
def inner_wrapper(*args, **kwargs):
14+
function(*args, **kwargs)
15+
blocker.set()
16+
return False
17+
18+
def wrapper(*args, **kwargs):
19+
# if this is the main thread then simply return function
20+
if threading.current_thread().name == SCP_MAIN_THREAD_NAME:
21+
return function(*args, **kwargs)
22+
Gdk.threads_add_idle(
23+
GLib.PRIORITY_DEFAULT_IDLE,
24+
inner_wrapper,
25+
*args,
26+
**kwargs
27+
)
28+
blocker.wait()
29+
30+
return wrapper

0 commit comments

Comments
 (0)