From 606fda7b69e62a9de519bcb28007005e03b90cb9 Mon Sep 17 00:00:00 2001
From: Skylar Kelty <S.Kelty@kent.ac.uk>
Date: Tue, 29 Jul 2014 08:30:41 +0100
Subject: [PATCH] MDL-46529 - Adhoc task queue can fail if task class has been
 deleted

---
 lib/classes/task/manager.php  |  6 ++++++
 lib/tests/adhoc_task_test.php | 32 ++++++++++++++++++++++++++++++++
 2 files changed, 38 insertions(+)

diff --git a/lib/classes/task/manager.php b/lib/classes/task/manager.php
index e2ec497..5eec524 100644
--- a/lib/classes/task/manager.php
+++ b/lib/classes/task/manager.php
@@ -419,6 +419,12 @@ class manager {
                 $classname = '\\' . $record->classname;
                 $task = self::adhoc_task_from_record($record);
 
+                // MDL-46529 - The class may not still be available.
+                if (!$task) {
+                    $lock->release();
+                    continue;
+                }
+
                 $task->set_lock($lock);
                 if (!$task->is_blocking()) {
                     $cronlock->release();
diff --git a/lib/tests/adhoc_task_test.php b/lib/tests/adhoc_task_test.php
index 174e54c..bacc14b 100644
--- a/lib/tests/adhoc_task_test.php
+++ b/lib/tests/adhoc_task_test.php
@@ -67,4 +67,36 @@ class core_adhoc_task_testcase extends advanced_testcase {
         $task = \core\task\manager::get_next_adhoc_task($now);
         $this->assertNull($task);
     }
+
+    public function test_adhoc_task_queue_fail() {
+        global $DB;
+
+        $this->resetAfterTest(true);
+
+        // Create a task that should fail.
+        $DB->insert_record('task_adhoc', array(
+            'id' => 1,
+            'classname' => 'thiswillfail',
+            'component' => 'core',
+            'blocking' => 0,
+            'nextruntime' => time() - 1,
+            'faildelay' => 0,
+            'customdata' => ''
+        ));
+
+
+        // Create an adhoc task.
+        $task = new \core\task\adhoc_test_task();
+
+        // Queue it.
+        $task = \core\task\manager::queue_adhoc_task($task);
+
+        // Get it from the scheduler, this will fail if get_next_adhoc_task returns the invalid
+        // object we created first.
+        $task = \core\task\manager::get_next_adhoc_task(time());
+        $this->assertNotNull($task);
+        $task->execute();
+
+        \core\task\manager::adhoc_task_complete($task);
+    }
 }
-- 
2.0.3

