Spawning a new worker process fails: Cannot serialize a running task

Hi everyone,

I am working on image acquisition for a camera. The main task is to continuously taking images and put them in sharred memory for other programs to grab. The main function is just a simple while loop which calls an external C function (camera API) to take an image, then put the image and its timestamp in the pre-attached shared arrays.

function work(camera::Camera, remcam::RemoteCamera)
    # set acquisition mode
    set_acquisitionmode(camera, "Continuous")

    # begin acquisition
    @info "start acquisition loop "

    start(camera)
    counter = 0
    
    while true
        #get image
        img =
        try
            SpinnakerCameras.next_image(camera, 1)
        catch ex
            @warn "image corrupted"
            if (!isa(ex, SpinnakerCameras.CallError) ||
                ex.code != SpinnakerCameras.SPINNAKER_ERR_TIMEOUT)
                rethrow(ex)
            end
            nothing
        end

       # check image completeness
        if img.incomplete == 1 && img.status != 0
           @goto clear_img
       end

       counter +=1

        # get data and timestamp from image handle
        ts = img.timestamp
        img_data = @view img.data[:,:]
   
        # lock and write information to shared arrays
        wrlock(remcam.img,1) do
            copyto!(remcam.img, img)
        end
        wrlock(remcam.imgTime,1) do
            remcam.imgTime[1] = ts
        end

        @label clear_img
            finalize(img)

    end
    nothing
end
  

When it runs locally, it works perfectly fine. However, when I use @spawn when calling the function and fetch the Future

fetch(@spawn SpinnakerCameras.work(camera,remcam))

it produces an error message

cannot serialize a running Task
error(s::String) at error.jl:33
serialize(s::Distributed.ClusterSerializer{Sockets.TCPSocket}, t::Task) at Serialization.jl:445
serialize_any(s::Distributed.ClusterSerializer{Sockets.TCPSocket}, x::Any) at Serialization.jl:657
serialize(s::Distributed.ClusterSerializer{Sockets.TCPSocket}, x::Any) at Serialization.jl:636
serialize_any(s::Distributed.ClusterSerializer{Sockets.TCPSocket}, x::Any) at Serialization.jl:657
serialize(s::Distributed.ClusterSerializer{Sockets.TCPSocket}, x::Any) at Serialization.jl:636
serialize_any(s::Distributed.ClusterSerializer{Sockets.TCPSocket}, x::Any) at Serialization.jl:657
serialize(s::Distributed.ClusterSerializer{Sockets.TCPSocket}, x::Any) at Serialization.jl:636
serialize_global_from_main(s::Distributed.ClusterSerializer{Sockets.TCPSocket}, sym::Symbol) at clusterserialize.jl:155
#6 at clusterserialize.jl:101 [inlined]
foreach at abstractarray.jl:2141 [inlined]
serialize(s::Distributed.ClusterSerializer{Sockets.TCPSocket}, t::Core.TypeName) at clusterserialize.jl:101
serialize_type_data(s::Distributed.ClusterSerializer{Sockets.TCPSocket}, t::DataType) at Serialization.jl:539
serialize_type(s::Distributed.ClusterSerializer{Sockets.TCPSocket}, t::DataType, ref::Bool) at Serialization.jl:583
serialize_any(s::Distributed.ClusterSerializer{Sockets.TCPSocket}, x::Any) at Serialization.jl:653
serialize(s::Distributed.ClusterSerializer{Sockets.TCPSocket}, x::Any) at Serialization.jl:636
serialize_msg(s::Distributed.ClusterSerializer{Sockets.TCPSocket}, o::Distributed.CallMsg{:call}) at messages.jl:78
#invokelatest#2 at essentials.jl:708 [inlined]
invokelatest at essentials.jl:706 [inlined]
send_msg_(w::Distributed.Worker, header::Distributed.MsgHeader, msg::Distributed.CallMsg{:call}, now::Bool) at messages.jl:174
send_msg at messages.jl:122 [inlined]
#remotecall#140 at remotecall.jl:365 [inlined]
remotecall(::Function, ::Distributed.Worker) at remotecall.jl:364
remotecall(::Function, ::Int64; kwargs::Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}) at remotecall.jl:376
remotecall at remotecall.jl:376 [inlined]
spawnat(p::Int64, thunk::Function) at macros.jl:15
spawn_somewhere(thunk::Function) at macros.jl:17
top-level scope at macros.jl:50
eval at boot.jl:360 [inlined]

I want to run this routine on a different worker process because I want the camera to work like a server which takes commands from RELP and operates in the background. Or is it better to run it locally and use another RELP to communicate with the camera as a client instead?

Appreciate any help!

Best,

Sitthichat

1 Like