It’s a race condition I suppose. The first remote call (thanks to @async) doesn’t execute until the loop comes around a second time and modifies moo.
I’d say the cleanest option is B; copy the object inside the loop. But if you must do it the other way, this works
function doit(moo_in::Moo, fnames)
moo = deepcopy(moo_in) # LINE A
wait_for = Future[]
for (ipid, pid) in enumerate(workers())
moo.fname = fnames[ipid]
@info "sending $(moo) from manager to process $pid"
push!(wait_for, remotecall(say, pid, moo))
end
wait.(wait_for)
@info "Done."
end