don't freeze gui during long makepkg tasks and avoid zombis with pamac-tray

This commit is contained in:
guinux 2013-11-27 16:11:47 +01:00
parent 3b4a29bcf9
commit 10c2dfebd5
2 changed files with 31 additions and 23 deletions

View File

@ -19,9 +19,10 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
from gi.repository import Gtk, GObject, Notify from gi.repository import Gtk, GObject, Notify
from subprocess import Popen from subprocess import call
import dbus import dbus
from dbus.mainloop.glib import DBusGMainLoop from dbus.mainloop.glib import DBusGMainLoop
from threading import Thread
from pamac import common from pamac import common
@ -64,10 +65,10 @@ class Tray:
self.update_icon(icon, info) self.update_icon(icon, info)
def execute_update(self, widget, event, data = None): def execute_update(self, widget, event, data = None):
Popen(['/usr/bin/pamac-updater']) Thread(target = call, args = (['/usr/bin/pamac-updater'],)).start()
def execute_manager(self, widget, event, data = None): def execute_manager(self, widget, event, data = None):
Popen(['/usr/bin/pamac-manager']) Thread(target = call, args = (['/usr/bin/pamac-manager'],)).start()
def quit_tray(self, widget, data = None): def quit_tray(self, widget, data = None):
Gtk.main_quit() Gtk.main_quit()
@ -80,7 +81,7 @@ class Tray:
def activate_cb(self, widget, data = None): def activate_cb(self, widget, data = None):
if icon == update_icon: if icon == update_icon:
Popen(['/usr/bin/pamac-updater']) Thread(target = call, args = (['/usr/bin/pamac-updater'],)).start()
def update_icon(self, icon, info): def update_icon(self, icon, info):
self.statusIcon.set_from_file(icon) self.statusIcon.set_from_file(icon)
@ -90,7 +91,7 @@ class Tray:
self.statusIcon.set_visible(boolean) self.statusIcon.set_visible(boolean)
def refresh(): def refresh():
Popen(['/usr/bin/pamac-refresh']) Thread(target = call, args = (['/usr/bin/pamac-refresh'],)).start()
def set_icon(update_data): def set_icon(update_data):
global icon global icon

View File

@ -29,6 +29,7 @@ import fnmatch
#from urllib.parse import urlparse #from urllib.parse import urlparse
import dbus import dbus
from dbus.mainloop.glib import DBusGMainLoop from dbus.mainloop.glib import DBusGMainLoop
import signal
from pamac import config, common, aur from pamac import config, common, aur
@ -134,18 +135,6 @@ def config_dbus_signals():
bus.add_signal_receiver(log_error, dbus_interface = "org.manjaro.pamac", signal_name = "EmitLogError") bus.add_signal_receiver(log_error, dbus_interface = "org.manjaro.pamac", signal_name = "EmitLogError")
bus.add_signal_receiver(log_warning, dbus_interface = "org.manjaro.pamac", signal_name = "EmitLogWarning") bus.add_signal_receiver(log_warning, dbus_interface = "org.manjaro.pamac", signal_name = "EmitLogWarning")
def write_to_buffer(fd, condition):
if condition == GObject.IO_IN: # if there's something interesting to read
line = fd.readline().decode(encoding='UTF-8')
#print(line.rstrip('\n'))
progress_buffer.insert_at_cursor(line)
progress_bar.pulse()
while Gtk.events_pending():
Gtk.main_iteration()
return True # FUNDAMENTAL, otherwise the callback isn't recalled
else:
return False # Raised an error: exit
def action_handler(action): def action_handler(action):
progress_label.set_text(action) progress_label.set_text(action)
@ -468,16 +457,34 @@ def prepare(**trans_flags):
return(error) return(error)
def check_finished_build(data): def check_finished_build(data):
def handle_timeout(*args):
raise Exception('timeout')
global to_build global to_build
global build_proc global build_proc
path = data[0] path = data[0]
pkg = data[1] pkg = data[1]
if build_proc.poll() is None: if build_proc.poll() is None:
progress_bar.pulse() # Build no finished : read stdout to push it to text_buffer
while Gtk.events_pending(): # add a timeout to stop reading stdout if too long
Gtk.main_iteration() # so the gui won't freeze
return True signal.signal(signal.SIGALRM, handle_timeout)
signal.setitimer(signal.ITIMER_REAL, 0.05) # 50 ms timeout
try:
line = build_proc.stdout.readline().decode(encoding='UTF-8')
#print(line.rstrip('\n'))
progress_buffer.insert_at_cursor(line)
progress_bar.pulse()
while Gtk.events_pending():
Gtk.main_iteration()
except Exception:
while Gtk.events_pending():
Gtk.main_iteration()
finally:
signal.alarm(0)
return True
elif build_proc.poll() == 0: elif build_proc.poll() == 0:
# Build successfully finished
built = [] built = []
# parse again PKGBUILD to have new pkg objects in case of a pkgver() function # parse again PKGBUILD to have new pkg objects in case of a pkgver() function
# was used so pkgver was changed during build process # was used so pkgver was changed during build process
@ -525,6 +532,7 @@ def check_finished_build(data):
action_long_handler(_('Build process failed.')) action_long_handler(_('Build process failed.'))
return False return False
elif build_proc.poll() == 1: elif build_proc.poll() == 1:
# Build finish with an error
ProgressCancelButton.set_visible(False) ProgressCancelButton.set_visible(False)
ProgressCloseButton.set_visible(True) ProgressCloseButton.set_visible(True)
action_long_handler(_('Build process failed.')) action_long_handler(_('Build process failed.'))
@ -625,10 +633,9 @@ def build_next():
progress_expander.set_expanded(True) progress_expander.set_expanded(True)
ProgressWindow.show() ProgressWindow.show()
build_proc = subprocess.Popen(["makepkg", "-cf"], cwd = path, stdout = subprocess.PIPE, stderr=subprocess.STDOUT) build_proc = subprocess.Popen(["makepkg", "-cf"], cwd = path, stdout = subprocess.PIPE, stderr=subprocess.STDOUT)
GObject.io_add_watch(build_proc.stdout, GObject.IO_IN, write_to_buffer)
while Gtk.events_pending(): while Gtk.events_pending():
Gtk.main_iteration() Gtk.main_iteration()
GObject.timeout_add(500, check_finished_build, (path, pkg)) GObject.timeout_add(100, check_finished_build, (path, pkg))
def finalize(): def finalize():
if To_Add() or To_Remove(): if To_Add() or To_Remove():