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
--- 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