https://issues.qgis.org/https://issues.qgis.org/favicon.ico2018-12-05T16:55:14ZQGIS Issue TrackingQGIS Application - Bug report #20711: QgsTask and task manager cause crash when used in function scopehttps://issues.qgis.org/issues/20711?journal_id=969212018-12-05T16:55:14ZGiovanni Manghigiovanni.manghi@gmail.com
<ul><li><strong>Priority</strong> changed from <i>Normal</i> to <i>High</i></li><li><strong>Status</strong> changed from <i>Open</i> to <i>Feedback</i></li><li><strong>Category</strong> changed from <i>PyQGIS Console</i> to <i>Python bindings / sipify</i></li></ul><p>Please add the description also here, thanks.</p> QGIS Application - Bug report #20711: QgsTask and task manager cause crash when used in function scopehttps://issues.qgis.org/issues/20711?journal_id=969432018-12-05T23:02:19ZGraham Duls
<ul></ul><p>QGIS version 3.4.2 If you define a task and add it to the task manager within a function scope, it will cause the task to either not execute properly or, at worst, crash QGIS. Consider the following code:</p>
<pre>
import random
from time import sleep
from qgis.core import QgsApplication, QgsTask, QgsMessageLog, Qgis
MESSAGE_CATEGORY = 'Wasting time'
def do_task(task, wait_time):
"""
Raises an exception to abort the task.
Returns a result if success.
The result will be passed together with the exception (None in
the case of success) to the on_finished method
"""
QgsMessageLog.logMessage('Started task {}'.format(task.description()),
MESSAGE_CATEGORY, Qgis.Info)
wait_time = wait_time / 100
total = 0
iterations = 0
for i in range(100):
sleep(wait_time)
# use task.setProgress to report progress
task.setProgress(i)
arandominteger = random.randint(0, 500)
total += arandominteger
iterations += 1
# check task.isCanceled() to handle cancellation
if task.isCanceled():
stopped(task)
return None
# raise an exception to abort the task
if arandominteger == 42:
raise Exception('bad value!')
return {'total': total, 'iterations': iterations,
'task': task.description()}
def stopped(task):
QgsMessageLog.logMessage(
'Task "{name}" was canceled'.format(
name=task.description()),
MESSAGE_CATEGORY, Qgis.Info)
def completed(exception, result=None):
"""This is called when do_task is finished.
Exception is not None if do_task raises an exception.
Result is the return value of do_task."""
if exception is None:
if result is None:
QgsMessageLog.logMessage(
'Completed with no exception and no result '\
'(probably manually canceled by the user)',
MESSAGE_CATEGORY, Qgis.Warning)
else:
QgsMessageLog.logMessage(
'Task {name} completed\n'
'Total: {total} ( with {iterations} '
'iterations)'.format(
name=result['task'],
total=result['total'],
iterations=result['iterations']),
MESSAGE_CATEGORY, Qgis.Info)
else:
QgsMessageLog.logMessage("Exception: {}".format(exception),
MESSAGE_CATEGORY, Qgis.Critical)
raise exception
# Create and execute a few tasks
task1 = QgsTask.fromFunction(u'Waste cpu 1', do_task,
on_finished=completed, wait_time=4)
task2 = QgsTask.fromFunction(u'Waste cpu 2', do_task,
on_finished=completed, wait_time=3)
QgsApplication.taskManager().addTask(task1)
QgsApplication.taskManager().addTask(task2)
</pre>
<p>If you put this in the script editor in QGIS and execute it, it will run just fine. The user can cancel. The exceptions are raised, occasionally. All is well. Now if you replace the last block of the code to be within a function scope, like so:</p>
<pre>
def task_create_and_execute():
# Create and execute a few tasks
task1 = QgsTask.fromFunction(u'Waste cpu 1', do_task,
on_finished=completed, wait_time=4)
task2 = QgsTask.fromFunction(u'Waste cpu 2', do_task,
on_finished=completed, wait_time=3)
QgsApplication.taskManager().addTask(task1)
QgsApplication.taskManager().addTask(task2)
task_create_and_execute()
</pre>
<p>Now when you run the script you will find that either task1 will appear to run, but the completed() function will never be reached (task2 will NOT run) or QGIS will crash. If you run it twice, QGIS will most surely crash. This will also happen when using the class method.</p> QGIS Application - Bug report #20711: QgsTask and task manager cause crash when used in function scopehttps://issues.qgis.org/issues/20711?journal_id=969622018-12-06T08:37:46ZGiovanni Manghigiovanni.manghi@gmail.com
<ul><li><strong>Status</strong> changed from <i>Feedback</i> to <i>Open</i></li></ul>