Electron.jl icon indicating copy to clipboard operation
Electron.jl copied to clipboard

Electron.jl does not work with multiple tasks

Open tkf opened this issue 6 years ago • 1 comments

It looks like Electron.jl cannot be used with multiple tasks (@async, @spawn, etc.). This is because touching app.connection from multiple tasks violates the basic sequential assumption of the IPC used in Electron.jl.

For example, if you check out https://github.com/tkf/ElectronProgressBars.jl and run examples/demo.jl as a script (i.e., not in REPL), you will likely see something like

$ julia --startup-file=no examples/demo.jl
┌ Error: Error from function: #17
│   exception =
│    KeyError: key "data" not found
│    Stacktrace:
│     [1] getindex(::Dict{String,Any}, ::String) at ./dict.jl:477
│     [2] run(::Electron.Window, ::String) at /home/takafumi/.julia/dev/Electron/src/Electron.jl:257
│     [3] (::ElectronProgressBars.var"#17#18"{UInt64,ElectronProgressBars.ElectronProgressBarLogger,Symbol})() at /home/takafumi/.julia/dev/ElectronProgressBars/src/ElectronProgressBars.jl:223
│     [4] message_handler(::Channel{Any}) at /home/takafumi/.julia/dev/ElectronProgressBars/src/ElectronProgressBars.jl:65
│     [5] (::Base.var"#636#637"{typeof(ElectronProgressBars.message_handler),Channel{Any}})() at ./channels.jl:129
└ @ ElectronProgressBars ~/.julia/dev/ElectronProgressBars/src/ElectronProgressBars.jl:67

This happens at the end of

https://github.com/davidanthoff/Electron.jl/blob/bc0de51f8d373a299c752879d18c827013b1d865/src/Electron.jl#L253-L258

where retval is empty because it is (presumably) coming from the closewindow response

https://github.com/davidanthoff/Electron.jl/blob/bc0de51f8d373a299c752879d18c827013b1d865/src/main.js#L60-L64

But why? AFAICT, Electron.jl's IPC mechanism crucially depends on that requests and responses are sequentialized. However this is not guaranteed because req_response directly reads and writes the app.connection pipe:

https://github.com/davidanthoff/Electron.jl/blob/bc0de51f8d373a299c752879d18c827013b1d865/src/Electron.jl#L217-L224

It becomes problematic if run is called via task. Indeed, that's what I'm doing.

IMHO no code other than the main loop launched in Application should touch the raw pipe and req_response should communicate with the main loop with a Channel. This way all the requests and responses would be sequentialized. One benefit would be that run become "thread-safe."

tkf avatar Oct 18 '19 03:10 tkf

Yes, agreed, that seems the right way to handle that!

davidanthoff avatar Oct 19 '19 11:10 davidanthoff