Refactor all of the threading.Threads into QThreads, and quit them all when canceling the server. When canceling the compression thread, specifically mass a cancel message into the Web and ZipWriter objects to make the bail out on compression early

This commit is contained in:
Micah Lee 2018-09-17 20:55:54 -07:00
parent f0bf9fb727
commit 0dc03ecd4c
6 changed files with 196 additions and 106 deletions

View file

@ -17,7 +17,6 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
import threading
import os
from PyQt5 import QtCore, QtWidgets, QtGui
@ -28,6 +27,7 @@ from onionshare.web import Web
from .file_selection import FileSelection
from .downloads import Downloads
from .threads import CompressThread
from ..mode import Mode
from ..widgets import Alert
@ -39,6 +39,9 @@ class ShareMode(Mode):
"""
Custom initialization for ReceiveMode.
"""
# Threads start out as None
self.compress_thread = None
# Create the Web object
self.web = Web(self.common, True, False)
@ -161,28 +164,13 @@ class ShareMode(Mode):
self._zip_progress_bar.total_files_size = ShareMode._compute_total_size(self.filenames)
self.status_bar.insertWidget(0, self._zip_progress_bar)
# Prepare the files for sending in a new thread
def finish_starting_server(self):
# Prepare files to share
def _set_processed_size(x):
if self._zip_progress_bar != None:
self._zip_progress_bar.update_processed_size_signal.emit(x)
try:
self.web.set_file_info(self.filenames, processed_size_callback=_set_processed_size)
self.app.cleanup_filenames.append(self.web.zip_filename)
# Only continue if the server hasn't been canceled
if self.server_status.status != self.server_status.STATUS_STOPPED:
self.starting_server_step3.emit()
self.start_server_finished.emit()
except OSError as e:
self.starting_server_error.emit(e.strerror)
return
t = threading.Thread(target=finish_starting_server, kwargs={'self': self})
t.daemon = True
t.start()
# prepare the files for sending in a new thread
self.compress_thread = CompressThread(self)
self.compress_thread.success.connect(self.starting_server_step3.emit)
self.compress_thread.success.connect(self.start_server_finished.emit)
self.compress_thread.error.connect(self.starting_server_error.emit)
self.server_status.server_canceled.connect(self.compress_thread.cancel)
self.compress_thread.start()
def start_server_step3_custom(self):
"""
@ -222,6 +210,15 @@ class ShareMode(Mode):
self.update_downloads_in_progress()
self.file_selection.file_list.adjustSize()
def cancel_server_custom(self):
"""
Stop the compression thread on cancel
"""
if self.compress_thread:
self.common.log('OnionShareGui', 'cancel_server: quitting compress thread')
self.compress_thread.cancel()
self.compress_thread.quit()
def handle_tor_broke_custom(self):
"""
Connection to Tor broke.

View file

@ -0,0 +1,60 @@
# -*- coding: utf-8 -*-
"""
OnionShare | https://onionshare.org/
Copyright (C) 2014-2018 Micah Lee <micah@micahflee.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from PyQt5 import QtCore
class CompressThread(QtCore.QThread):
"""
Compresses files to be shared
"""
success = QtCore.pyqtSignal()
error = QtCore.pyqtSignal(str)
def __init__(self, mode):
super(CompressThread, self).__init__()
self.mode = mode
self.mode.common.log('CompressThread', '__init__')
# prepare files to share
def set_processed_size(self, x):
if self.mode._zip_progress_bar != None:
self.mode._zip_progress_bar.update_processed_size_signal.emit(x)
def run(self):
self.mode.common.log('CompressThread', 'run')
try:
if self.mode.web.set_file_info(self.mode.filenames, processed_size_callback=self.set_processed_size):
self.success.emit()
else:
# Cancelled
pass
self.mode.app.cleanup_filenames.append(self.mode.web.zip_filename)
except OSError as e:
self.error.emit(e.strerror)
def cancel(self):
self.mode.common.log('CompressThread', 'cancel')
# Let the Web and ZipWriter objects know that we're canceling compression early
self.mode.web.cancel_compression = True
if self.mode.web.zip_writer:
self.mode.web.zip_writer.cancel_compression = True