enhancement
major
minor
defect
critical
major
minor
major
#30090
Scheduler: Ein beim Start fälliger Task wird beim Herunterfahren abgehängt, während er noch läuft (NullPointerException in TaskImpl.getLog())
Problem
Seit #30057 (Commit f26eab48b1) startet der Scheduler fällige Aufgaben, z. B. solche, die beim Systemstart geplant sind, bereits in seiner ersten Runde statt erst nach dem ersten Abfrageintervall. Bei einer Anwendung, die unmittelbar nach ihrem Start gestoppt wird (das Testaufbau-Skript von „TestMigrationRewrite“ startet und stoppt die Anwendung mehrmals), läuft nun regelmäßig die Aufgabe „RefreshUsersTask“ zum Zeitpunkt des Herunterfahrens.
Jenkins tl-ci-pr Build 789 (PR !2089, steht in keinem Zusammenhang mit dem Scheduler), ScriptedTest(shard-1)#test.com.top_logic.test.app.rewrite.TestMigrationRewrite TestUI: „Während der Testausführung wurde ein Fehler protokolliert! Es wurden 5 Fehler protokolliert“:
Der Thread „RefreshUsersTask“ wurde durch eine nicht abgefangene Ausnahme vom Typ „java.lang.NullPointerException“ zerstört. Meldung: „com.top_logic.util.sched.task.log.TaskLog.getCurrentResult()“ kann nicht aufgerufen werden, da der Rückgabewert von „com.top_logic.util.sched.task.impl.TaskImpl.getLog()“ null ist
MultiError: Das Beenden der Aufgabe „RefreshUsersTask“ ist nach 20 Versuchen fehlgeschlagen. Es wird davon ausgegangen, dass die Aufgabe nicht beendet werden soll.
in com.top_logic.util.sched.task.impl.TaskImpl.signalStop(TaskImpl.java:835)
in com.top_logic.basic.sched.BatchImpl.signalShutdown(BatchImpl.java:73)
bei com.top_logic.util.sched.Scheduler.signalShutdown(Scheduler.java:692)
bei com.top_logic.util.sched.Scheduler.shutDownThreadWithThreadContext(Scheduler.java:2180)
...
Ursache: java.lang.NullPointerException: „TaskLog.getState()“ kann nicht aufgerufen werden, da der Rückgabewert von „TaskImpl.getLog()“ null ist
in com.top_logic.util.sched.task.impl.TaskImpl.trySignalStopClusterGlobal(TaskImpl.java:886)
Zeitachse aus dem Protokoll: Aufgabe gestartet um 23:27:36,265; Scheduler.shutDown() beginnt um 23:27:36,276 und kehrt genau 5 s später zurück (shutdown-join-time), wobei der Dispatch-Thread noch aktiv ist („Scheduler läuft noch“). shutDown() hebt anschließend die Registrierung aller Aufgaben auf, wodurch diese abgekoppelt und ihr Log auf null gesetzt wird, während sich der Dispatch-Thread noch in seiner Abschaltphase befindet (er wartet bis zum time-to-kill) und der Aufgaben-Thread noch läuft. Beide greifen dann auf das fehlende Log zu.
Analyse und Behebung folgen in den Kommentaren.