# Share and modify struct from master in worker

**URL:** https://discourse.julialang.org/t/share-and-modify-struct-from-master-in-worker/43952
**Category:** General Usage
**Tags:** distributed
**Created:** [July 30, 2020, 9:07am UTC](https://discourse.julialang.org/t/share-and-modify-struct-from-master-in-worker/43952 "2020-07-30T09:07:38Z")
**Posts on this page:** 9
**Page:** 1

<div class="post-metadata">

### Author: ![Iulian.Cioarca](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/iulian.cioarca/32/30166_2.png) [@Iulian.Cioarca](https://discourse.julialang.org/u/Iulian.Cioarca)
#### Post date: [July 30, 2020, 9:07am UTC](https://discourse.julialang.org/t/share-and-modify-struct-from-master-in-worker/43952/1 "2020-07-30T09:07:38Z")

</div>

I am developing a GUI using [CImGui.jl](https://github.com/Gnimuc/CImGui.jl) and want to run it in a separate process and communicate to/from the master process by modifying a struct. The struct contents could be anything: Array, Strings, file handles.  
I cannot return anything from the remote process because CImGui runs and refreshes in a while loop, so returning from the function would close the gui.  
I will not post the actual gui code, but a very simplified example:

```julia
using Distributed
addprocs(1)
@everywhere struct Data
    crt_text
    cond
end
@everywhere gui = Data(["abc"], [true])
# basic test
@everywhere function run_gui()
    cond = true
    while(cond)
        println(gui.crt_text[1])
        gui.crt_text[1] = "xyz"
        sleep(0.5)
        cond = gui.cond[1] #the actual gui will have a CImGUI dedicated close button
    end
    return nothing
end
#check data before spwan
gui.crt_text[1]
@spawnat 2 run_gui()
# stop execution
@everywhere gui.cond[1] = false
# check data after spawn
gui.crt_text[1]

```

After execution of `run_gui()` I was expecting `gui.crt_text[1]` to be `xyz`, but it was not modified. How can I achieve this? Thank you!

---

<div class="post-metadata">

### Author: ![oheil](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oheil/32/220745_2.png) [@oheil](https://discourse.julialang.org/u/oheil)
#### Post date: [July 30, 2020, 9:18am UTC](https://discourse.julialang.org/t/share-and-modify-struct-from-master-in-worker/43952/2 "2020-07-30T09:18:05Z")

</div>

> [@Iulian.Cioarca](#):
>
> ```julia
> @everywhere function run_gui()
> cond = true
> while(cond)
> println(gui.crt_text[1])
> gui.crt_text[1] = "xyz"
> sleep(0.5)
> cond = gui.cond[1] #the actual gui will have a CImGUI dedicated close button
> end
> return nothing
> end
> 
> ```

Setting the value

```julia
gui.crt_text[1] = "xyz"

```

lacks a @everywhere, this works as you expected:

```julia
@everywhere function run_gui()
    cond = true
    while(cond)
        println(gui.crt_text[1])
        @everywhere gui.crt_text[1] = "xyz"
        sleep(0.5)
        cond = gui.cond[1] #the actual gui will have a CImGUI dedicated close button
    end
    return nothing
end

```

---

<div class="post-metadata">

### Author: ![Iulian.Cioarca](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/iulian.cioarca/32/30166_2.png) [@Iulian.Cioarca](https://discourse.julialang.org/u/Iulian.Cioarca)
#### Post date: [July 30, 2020, 9:40am UTC](https://discourse.julialang.org/t/share-and-modify-struct-from-master-in-worker/43952/3 "2020-07-30T09:40:32Z")

</div>

Thank you very much! I thought that `@everywhere` should be used only in the master process.

---

<div class="post-metadata">

### Author: ![oheil](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oheil/32/220745_2.png) [@oheil](https://discourse.julialang.org/u/oheil)
#### Post date: [July 30, 2020, 9:45am UTC](https://discourse.julialang.org/t/share-and-modify-struct-from-master-in-worker/43952/4 "2020-07-30T09:45:30Z")

</div>

> [@Iulian.Cioarca](#):
>
> should be used only

Can you share a link to the docs? Is this somewhere in the docs? May be it is the case, but I don’t know.

---

<div class="post-metadata">

### Author: ![Iulian.Cioarca](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/iulian.cioarca/32/30166_2.png) [@Iulian.Cioarca](https://discourse.julialang.org/u/Iulian.Cioarca)
#### Post date: [July 30, 2020, 9:48am UTC](https://discourse.julialang.org/t/share-and-modify-struct-from-master-in-worker/43952/5 "2020-07-30T09:48:29Z")

</div>

[https://docs.julialang.org/en/v1/stdlib/Distributed/#Distributed.@everywhere](https://docs.julialang.org/en/v1/stdlib/Distributed/#Distributed.@everywhere)

```julia
@everywhere [procs()] expr
Execute an expression under Main on all procs. Errors on any of the processes are collected into a CompositeException and thrown. For example:

@everywhere bar = 1
will define Main.bar on all processes.

Unlike @spawnat, @everywhere does not capture any local variables. Instead, local variables can be broadcast using interpolation:

foo = 1
@everywhere bar = $foo
The optional argument procs allows specifying a subset of all processes to have execute the expression.

Equivalent to calling remotecall_eval(Main, procs, expr).

```

It’s not clear for me from the docs that one could `@everywhere` in a worker.

---

<div class="post-metadata">

### Author: ![oheil](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oheil/32/220745_2.png) [@oheil](https://discourse.julialang.org/u/oheil)
#### Post date: [July 30, 2020, 9:52am UTC](https://discourse.julialang.org/t/share-and-modify-struct-from-master-in-worker/43952/6 "2020-07-30T09:52:04Z")

</div>

ok, but it doesn’t explicitly exclude it.

An alternative would be to return the altered gui struct:

```julia
@everywhere function run_gui()
    cond = true
    while(cond)
        println(gui.crt_text[1])
        gui.crt_text[1] = "xyz"
        sleep(0.5)
        cond = gui.cond[1] #the actual gui will have a CImGUI dedicated close button
    end
    return gui
end

```

and fetch it after stoping the process:

```julia
gui.crt_text[1]
s = @spawnat 2 run_gui()
# stop execution
@everywhere gui.cond[1] = false
# check data after spawn
gui=fetch(s)
gui.crt_text[1]

```

---

<div class="post-metadata">

### Author: ![Iulian.Cioarca](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/iulian.cioarca/32/30166_2.png) [@Iulian.Cioarca](https://discourse.julialang.org/u/Iulian.Cioarca)
#### Post date: [July 31, 2020, 5:26pm UTC](https://discourse.julialang.org/t/share-and-modify-struct-from-master-in-worker/43952/7 "2020-07-31T17:26:28Z")

</div>

True. Thanks again for your help!

---

<div class="post-metadata">

### Author: ![Iulian.Cioarca](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/iulian.cioarca/32/30166_2.png) [@Iulian.Cioarca](https://discourse.julialang.org/u/Iulian.Cioarca)
#### Post date: [August 7, 2020, 10:05am UTC](https://discourse.julialang.org/t/share-and-modify-struct-from-master-in-worker/43952/8 "2020-08-07T10:05:47Z")

</div>

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:

```julia
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:

```julia
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!

---

<div class="post-metadata">

### Author: ![oheil](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oheil/32/220745_2.png) [@oheil](https://discourse.julialang.org/u/oheil)
#### Post date: [August 7, 2020, 10:41am UTC](https://discourse.julialang.org/t/share-and-modify-struct-from-master-in-worker/43952/9 "2020-08-07T10:41:50Z")

</div>

> [@Iulian.Cioarca](#):
>
> ```julia
> # open comm
> arduino_main = LibSerialPort.open("COM3", 115200)
> # make it visible to the worker
> @everywhere arduino_worker = $arduino_main
> 
> ```

I am not sure, if above code is supposed to work as simple as it is.  
From  
[https://sigrok.org/api/libserialport/unstable/index.html](https://sigrok.org/api/libserialport/unstable/index.html)  
I see e.g.:

> ## Thread safety
> 
> Certain combinations of calls can be made concurrently, as follows.
> 
> - Calls using different ports may always be made concurrently, i.e. it is safe for separate threads to handle their own ports.
> - Calls using the same port may be made concurrently when one call is a read operation and one call is a write operation, i.e. it is safe to use separate “reader” and “writer” threads for the same port. See below for which operations meet these definitions.

and further important reading.  
Check you coding details according to the rules of libserialport.

There is also something about  
[https://docs.julialang.org/en/v1/manual/multi-threading/#Side-effects-and-mutable-function-arguments-1](https://docs.julialang.org/en/v1/manual/multi-threading/#Side-effects-and-mutable-function-arguments-1)

> ## [@threadcall](https://docs.julialang.org/en/v1/manual/multi-threading/#@threadcall-1)
> 
> External libraries, such as those called via [`ccall`](https://docs.julialang.org/en/v1/base/c/#ccall), pose a problem for Julia’s task-based I/O mechanism. If a C library performs a blocking operation, that prevents the Julia scheduler from executing any other tasks until the call returns.

I’m afraid that I’m not experienced enough in your specific task to help remotely.
