Runtime: Fix exception "Worker is disabled" when connecting while PLC runtime is starting.
authorEdouard Tisserant
Tue, 25 May 2021 15:05:38 +0200
changeset 2738 58f2e3f22934
parent 2737 38afed869ff6
child 2739 7278186a2083
Runtime: Fix exception "Worker is disabled" when connecting while PLC runtime is starting.

Pyro/wamp/UI delegate jobs to Worker, causing race condition if worker isn't already started.
Added a function to ensure that Worker is already created when pyro or UI starts
Beremiz_service.py
--- a/Beremiz_service.py	Mon May 24 14:33:54 2021 +0200
+++ b/Beremiz_service.py	Tue May 25 15:05:38 2021 +0200
@@ -546,24 +546,35 @@
         except Exception:
             LogMessageAndException(_("WAMP client startup failed. "))
 
-pyro_thread_started = Lock()
-pyro_thread_started.acquire()
-pyro_thread = Thread(target=pyroserver.PyroLoop,
-                     kwargs=dict(when_ready=pyro_thread_started.release),
-                     name="PyroThread")
-pyro_thread.start()
-
-# Wait for pyro thread to be effective
-pyro_thread_started.acquire()
-
-pyroserver.PrintServerInfo()
-
-# Beremiz IDE detects LOCAL:// runtime is ready by looking
-# for self.workdir in the daemon's stdout.
-sys.stdout.write(_("Current working directory :") + WorkingDir + "\n")
-sys.stdout.flush()
-
-if havetwisted or havewx:
+def FirstWorkerJob():
+    """
+    RPC through pyro/wamp/UI may lead to delegation to Worker,
+    then this function ensures that Worker is already
+    created when pyro starts
+    """
+    global pyro_thread, pyroserver, ui_thread, reactor, twisted_reactor_thread_id
+
+    pyro_thread_started = Lock()
+    pyro_thread_started.acquire()
+    pyro_thread = Thread(target=pyroserver.PyroLoop,
+                         kwargs=dict(when_ready=pyro_thread_started.release),
+                         name="PyroThread")
+
+    pyro_thread.start()
+
+    # Wait for pyro thread to be effective
+    pyro_thread_started.acquire()
+
+    pyroserver.PrintServerInfo()
+
+    # Beremiz IDE detects LOCAL:// runtime is ready by looking
+    # for self.workdir in the daemon's stdout.
+    sys.stdout.write(_("Current working directory :") + WorkingDir + "\n")
+    sys.stdout.flush()
+
+    if not (havetwisted or havewx):
+        return
+
     ui_thread_started = Lock()
     ui_thread_started.acquire()
     if havetwisted:
@@ -592,9 +603,10 @@
     ui_thread_started.acquire()
     print("UI thread started successfully.")
 
+    runtime.GetPLCObjectSingleton().AutoLoad(autostart)
+
 try:
-    runtime.MainWorker.runloop(
-        runtime.GetPLCObjectSingleton().AutoLoad, autostart)
+    runtime.MainWorker.runloop(FirstWorkerJob)
 except KeyboardInterrupt:
     pass