diff --git a/src/xpra/server/source.py b/src/xpra/server/source.py index 3761acac05..11b0fbe3ee 100644 --- a/src/xpra/server/source.py +++ b/src/xpra/server/source.py @@ -1548,7 +1548,7 @@ def send_clipboard(self, packet): self.send_clipboard_enabled(msg) return #call compress_clibboard via the work queue: - self.encode_work_queue.put((self.compress_clipboard, packet)) + self.encode_work_queue.put((True, self.compress_clipboard, packet)) def compress_clipboard(self, packet): #Note: this runs in the 'encode' thread! @@ -2122,8 +2122,13 @@ def encode_loop(self): fn_and_args = self.encode_work_queue.get(True) if fn_and_args is None: return #empty marker + #some function calls are optional and can be skipped when closing: + #(but some are not, like encoder clean functions) + optional_when_closing = fn_and_args[0] + if optional_when_closing and self.is_closed(): + continue try: - fn_and_args[0](*fn_and_args[1:]) + fn_and_args[1](*fn_and_args[2:]) except Exception as e: if self.is_closed(): log("ignoring encoding error in %s as source is already closed:", fn_and_args[0]) diff --git a/src/xpra/server/window/window_source.py b/src/xpra/server/window/window_source.py index 390c81ce1d..31fb54ae04 100644 --- a/src/xpra/server/window/window_source.py +++ b/src/xpra/server/window/window_source.py @@ -518,7 +518,7 @@ def send_window_icon(self, window): #and delay sending it by a bit to allow basic icon batching: delay = max(50, int(self.batch_config.delay)) iconlog("send_window_icon(%s) wid=%s, icon=%s, compression scheduled in %sms", window, self.wid, surf, delay) - self.timeout_add(delay, self.call_in_encode_thread, self.compress_and_send_window_icon) + self.timeout_add(delay, self.call_in_encode_thread, True, self.compress_and_send_window_icon) def compress_and_send_window_icon(self): #this runs in the work queue @@ -1350,20 +1350,20 @@ def process_damage_region(self, damage_time, window, x, y, w, h, coding, options av_sync = options.get("av-sync", False) av_delay = self.av_sync_delay*int(av_sync) if not av_sync: - self.call_in_encode_thread(self.make_data_packet_cb, *item) + self.call_in_encode_thread(True, self.make_data_packet_cb, *item) else: #schedule encode via queue, after freezing the pixels: if not image.freeze(): avsynclog("Warning: failed to freeze image pixels for:") avsynclog(" %s", image) - self.call_in_encode_thread(self.make_data_packet_cb, *item) + self.call_in_encode_thread(True, self.make_data_packet_cb, *item) return self.encode_queue.append(item) l = len(self.encode_queue) if l>=self.encode_queue_max_size: av_delay = 0 #we must free some space! avsynclog("scheduling encode queue iteration in %ims, encode queue size=%i (max=%i)", av_delay, l, self.encode_queue_max_size) - self.timeout_add(av_delay, self.call_in_encode_thread, self.encode_from_queue) + self.timeout_add(av_delay, self.call_in_encode_thread, True, self.encode_from_queue) def encode_from_queue(self): #note: we use a queue here to ensure we preserve the order @@ -1413,7 +1413,7 @@ def encode_from_queue(self): return first_due = int(max(0, min(still_due)-time.time())*1000) avsynclog("encode_from_queue: first due in %ims, due list=%s", first_due, still_due) - self.timeout_add(first_due, self.call_in_encode_thread, self.encode_from_queue) + self.timeout_add(first_due, self.call_in_encode_thread, True, self.encode_from_queue) def make_data_packet_cb(self, window, w, h, damage_time, process_damage_time, wid, image, coding, sequence, options, flush): diff --git a/src/xpra/server/window/window_video_source.py b/src/xpra/server/window/window_video_source.py index 99c06c1505..9297d08113 100644 --- a/src/xpra/server/window/window_video_source.py +++ b/src/xpra/server/window/window_video_source.py @@ -234,14 +234,14 @@ def csc_encoder_clean(self): csce = self._csc_encoder if csce: self._csc_encoder = None - self.call_in_encode_thread(csce.clean) + self.call_in_encode_thread(False, csce.clean) def video_encoder_clean(self): """ Calls self._video_encoder.clean() from the encode thread """ ve = self._video_encoder if ve: self._video_encoder = None - self.call_in_encode_thread(ve.clean) + self.call_in_encode_thread(False, ve.clean) def parse_csc_modes(self, full_csc_modes):