Since it’s somehow related, I’ll ask for your help once more. First a bit more background about my project:
I’m writing this GUI as a front panel for a lab instrument(let’s say a power supply) for a remote lab session with students (COVID19 online measurements lab…). I want it to display information by query-ing the instrument (ex: what’s the output voltage) and also to be able to configure it by pushing buttons. So far so good, I managed to connect to the instrument and do all the above, but at the moment everything runs in the main process(so it blocks the REPL).
Now comes the tricky part: the student is supposed to send commands to the instrument from REPL and the GUI should update and provide visual feedback from another thread, without blocking the REPL. This means that the instrument handle responsible for instrument communication should be available both in main process(for the student REPL usage) and in the worker(for the GUI update).
This sharing should work simply by using @everywhere
. The problem I face is that I can communicate with the instrument from REPL, but whenever I try to refresh my GUI in the worker I get an Invalid handle
error.
My current workaround for this is to use Tasks
, but I’m afraid user experience will suffer when running 3-4 GUIs, all waiting to refresh while typing in the REPL.
It’s hard to provide and MWE in this case. To make things easier I tried to replicate this behavior using an arduino:
using Distributed
addprocs(1)
@everywhere using LibSerialPort
list_ports()
# open comm
arduino_main = LibSerialPort.open("COM3", 115200)
# make it visible to the worker
@everywhere arduino_worker = $arduino_main
# read some data in main process
readuntil(arduino_main, '\n', 1.0)
# try to read some data in worker
fetch(@spawnat 2 readuntil(arduino_worker, '\n', 1.0))
Communication from main process works fine (returns some 0s, doesn’t matter). Communication from worker fails with:
ERROR: On worker 2:
From C:\Julia 1.5.0\.julia\packages\LibSerialPort\xvkkM\src\wrap.jl: 141:
libserialport returned SP_ERR_ARG - Function was called with invalid arguments.
error at .\error.jl:33
handle_error at C:\Julia 1.5.0\.julia\packages\LibSerialPort\xvkkM\src\wrap.jl:136
sp_input_waiting at C:\Julia 1.5.0\.julia\packages\LibSerialPort\xvkkM\src\wrap.jl:660
bytesavailable at C:\Julia 1.5.0\.julia\packages\LibSerialPort\xvkkM\src\high-level-api.jl:420
readuntil at C:\Julia 1.5.0\.julia\packages\LibSerialPort\xvkkM\src\high-level-api.jl:402
readuntil at C:\Julia 1.5.0\.julia\packages\LibSerialPort\xvkkM\src\high-level-api.jl:386 [inlined]
#1 at D:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.5\Distributed\src\macros.jl:87
#103 at D:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.5\Distributed\src\process_messages.jl:290
run_work_thunk at D:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.5\Distributed\src\process_messages.jl:79
run_work_thunk at D:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.5\Distributed\src\process_messages.jl:88
#96 at .\task.jl:356
Stacktrace:
[1] #remotecall_fetch#143 at D:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.5\Distributed\src\remotecall.jl:394 [inlined]
[2] remotecall_fetch(::Function, ::Distributed.Worker, ::Distributed.RRID) at D:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.5\Distributed\src\remotecall.jl:386
[3] #remotecall_fetch#146 at D:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.5\Distributed\src\remotecall.jl:421 [inlined]
[4] remotecall_fetch at D:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.5\Distributed\src\remotecall.jl:421 [inlined]
[5] call_on_owner at D:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.5\Distributed\src\remotecall.jl:494 [inlined]
[6] fetch(::Future) at D:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.5\Distributed\src\remotecall.jl:533
[7] top-level scope at D:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.5\Distributed\src\macros.jl:99
Can someone explain why these particular variables representing communication sessions fail to be shared in a worker (being defined/communication opened in main process), and how to overcome this?
Thank you!