# \`eval\` scope problem and \`println\` problem for multithreading

**URL:** <https://discourse.julialang.org/t/eval-scope-problem-and-println-problem-for-multithreading/109333>\
**Category:** General Usage\
**Tags:** question, multithreading, eval, sockets\
**Created:** [January 27, 2024, 9:26am UTC](https://discourse.julialang.org/t/eval-scope-problem-and-println-problem-for-multithreading/109333 "2024-01-27T09:26:39Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![ccestbon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ccestbon/32/206575_2.png) [@ccestbon](https://discourse.julialang.org/u/ccestbon)\
**Post date:** [January 27, 2024, 9:26am UTC](https://discourse.julialang.org/t/eval-scope-problem-and-println-problem-for-multithreading/109333/1 "2024-01-27T09:26:39Z")

</div>

# Update 1:

Thanks for all the suggesions. I have modifed the code as follows:

```julia-auto
using Sockets

# server
server = listen(2000)
errormonitor(
  @async begin
    sock = accept(server)
    ex = quote my() = println("aa") end
    errormonitor(@async invokelatest(Core.eval, Main, ex))
    println("bb")
    errormonitor(@async invokelatest(Core.eval, Main, Meta.parse("my()")))
    sleep(1)
  end
)

# client
socket = connect(2000)

```

If I run the code from a file `julia blah.jl` , then “aa” is not printed out.

However, if I run the code from the REPL `julia> include("blah.jl")` , then “aa” is printed. Can anyone help and explain what is wrong when running `julia blah.jl`?

# original post:

Hello!

I am exploring `eval` and I encounter a problem. Here is my code:

```julia-auto
using Sockets

# server
server = listen(2000)
@async begin
  sock = accept(server)
  ex = quote my() = println("aa") end
  Core.eval(Main, ex)
  println("bb")
  my()
end

# client
socket = connect(2000)

```

The code is supposed to execute the function `my()`, but it only prints “bb” and “aa” is not printed out.

If I enter the code in the REPL as follows, however, the function `my()` works:

```julia-auto
ex = quote my() = println("aa") end
Core.eval(Main, ex)
println("bb")
my()

```

Can anyone tell me what is wrong with the first part of code when using `eval` with socket?

Thank you very much!

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [January 27, 2024, 9:42am UTC](https://discourse.julialang.org/t/eval-scope-problem-and-println-problem-for-multithreading/109333/2 "2024-01-27T09:42:59Z")

</div>

If I recall correctly, `@async` creates an anonymous function that is then run on the asynchronous task. This means that the function doesn’t see the newly defined function from your `eval` because of Julia’s world age mechanism.

Basically, functions don’t see the result of an `eval` until the return back to global scope, which the block in your `@async` doesn’t do.

---

<div class="post-metadata">

**Author:** ![ccestbon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ccestbon/32/206575_2.png) [@ccestbon](https://discourse.julialang.org/u/ccestbon)\
**Post date:** [January 27, 2024, 10:26am UTC](https://discourse.julialang.org/t/eval-scope-problem-and-println-problem-for-multithreading/109333/3 "2024-01-27T10:26:02Z")

</div>

Thaks for your reply. However, `my()` does not produce any error message, which indicates that there is a newly defined `my()` function in scope. Anyway, to address the issue of global scope, I change the code as follows:

```julia
using Sockets

# server
server = listen(2000)
@async begin
  sock = accept(server)
  ex = quote my() = println("aa") end
  Core.eval(Main, ex)
  println("bb")
  Core.eval(Main, Meta.parse("my()"))
end

# client
socket = connect(2000)

```

This way, I think there is no global scope concern any more. `my()` function is called in the global scope by `eval`. Still, `my()` is not executed.

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [January 27, 2024, 12:20pm UTC](https://discourse.julialang.org/t/eval-scope-problem-and-println-problem-for-multithreading/109333/4 "2024-01-27T12:20:44Z")

</div>

> [@ccestbon](#):
>
> Thaks for your reply. However, `my()` does not produce any error message, which indicates that there is a newly defined `my()` function in scope.

You don’t get an error because the `Task` spawned by `@async` captured it:

```julia
julia> t = @async begin
         sock = accept(server)
         ex = quote my() = println("aa") end
         Core.eval(Main, ex)
         println("bb")
         my()
       end

       # client
Task (runnable, started) @0x00007f960a3b5780

julia> socket = connect(2000)
bb
TCPSocket(RawFD(21) open, 0 bytes waiting)

julia> t
Task (failed) @0x00007f960a3b5780
MethodError: no method matching my()
The applicable method may be too new: running in world age 25655, while current world is 25656.

Closest candidates are:
  my() (method too new to be called from this world context.)
   @ Main REPL[3]:3

Stacktrace:
 [1] (::var"#1#2")()
   @ Main ./REPL[3]:6

```

> [@ccestbon](#):
>
> This way, I think there is no global scope concern any more. `my()` function is called in the global scope by `eval`. Still, `my()` is not executed.

With your modification, the message is printed for me. How are you running the example (from the REPL, from a file…)? Are you starting Julia with more than one thread, so that the async task has the opportunity to be scheduled?

---

<div class="post-metadata">

**Author:** ![ccestbon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ccestbon/32/206575_2.png) [@ccestbon](https://discourse.julialang.org/u/ccestbon)\
**Post date:** [January 27, 2024, 2:01pm UTC](https://discourse.julialang.org/t/eval-scope-problem-and-println-problem-for-multithreading/109333/5 "2024-01-27T14:01:11Z")

</div>

> You don’t get an error because the Task spawned by @async captured it

Thanks. As you pointed out, I can see the error message now. To show error messages, I have added `errormonitor` for `@async` and changed the code as follows:

```julia
using Sockets

# server
server = listen(2000)
errormonitor(
  @async begin
    sock = accept(server)
    ex = quote my() = println("aa") end
    Core.eval(Main, ex)
    println("bb")
    Core.eval(Main, Meta.parse("my()"))
  end
)

# client
socket = connect(2000)

```

If I run the above code from a .jl file, then only “bb” is printed out and there are no error messages. If I run the above code from the REPL, then both “bb” and “aa” are printed out. I started REPL using `julia` command, and the number of thread is

```julia
julia> Threads.nthreads()
1

```

I do not understand why results are different when using a file and the REPL, respectively. Can you help me figure this out? Thanks!

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [January 27, 2024, 5:52pm UTC](https://discourse.julialang.org/t/eval-scope-problem-and-println-problem-for-multithreading/109333/6 "2024-01-27T17:52:30Z")

</div>

> [@ccestbon](#):
>
> If I run the above code from a .jl file, then only “bb” is printed out and there are no error messages. If I run the above code from the REPL, then both “bb” and “aa” are printed out.

Odd, there is a hard vs soft scoping rule change, but that only involves some local scopes reassigning names shared with the global scope, which you don’t do. Couple questions for clarification:

1. when you say “run from a jl file” do you mean opening the REPL and running `include("blah.jl")`?
2. Did you close and reopen the REPL before each time you ran the code?

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [January 27, 2024, 7:20pm UTC](https://discourse.julialang.org/t/eval-scope-problem-and-println-problem-for-multithreading/109333/7 "2024-01-27T19:20:34Z")

</div>

I don’t have a definitive answer, but I guess it has to do with scheduling & `yield`ing. Can you try running julia with more than one thread (e.g. `julia -t 2`) and see if that fixes things?

---

<div class="post-metadata">

**Author:** ![simeonschaub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/simeonschaub/32/216566_2.png) [@simeonschaub](https://discourse.julialang.org/u/simeonschaub)\
**Post date:** [January 27, 2024, 8:05pm UTC](https://discourse.julialang.org/t/eval-scope-problem-and-println-problem-for-multithreading/109333/8 "2024-01-27T20:05:33Z")

</div>

You are probably looking for [`invokelatest`](https://docs.julialang.org/en/v1/base/base/#Base.invokelatest), e g. replacing `my()` with `invokelatest(my)`. Without `invokelatest` only methods that live in the world age of the containing functions are accessible, so not ones that are newly defined using `eval`. This is also why this happened to work when omitting the `@async`

---

<div class="post-metadata">

**Author:** ![ccestbon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ccestbon/32/206575_2.png) [@ccestbon](https://discourse.julialang.org/u/ccestbon)\
**Post date:** [January 28, 2024, 2:10am UTC](https://discourse.julialang.org/t/eval-scope-problem-and-println-problem-for-multithreading/109333/9 "2024-01-28T02:10:54Z")

</div>

Thanks for your reply.

> 1. when you say “run from a jl file” do you mean opening the REPL and running `include("blah.jl")`?

I run the file with the command `julia blah.jl` and it does not work as expected, i.e. “aa” is not printed. If I open the REPL and run with `include("blah.jl")`, then it works and “aa” is printed out.

> 1. Did you close and reopen the REPL before each time you ran the code?

Yes. I did close and repoen the REPL each time I ran the code.

---

<div class="post-metadata">

**Author:** ![ccestbon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ccestbon/32/206575_2.png) [@ccestbon](https://discourse.julialang.org/u/ccestbon)\
**Post date:** [January 28, 2024, 2:34am UTC](https://discourse.julialang.org/t/eval-scope-problem-and-println-problem-for-multithreading/109333/10 "2024-01-28T02:34:40Z")

</div>

I looked into `yield` before, but I haven’t figured out what is wrong. Running the file with `julia -t 2 blah.jl` does not fix the problem.

---

<div class="post-metadata">

**Author:** ![ccestbon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ccestbon/32/206575_2.png) [@ccestbon](https://discourse.julialang.org/u/ccestbon)\
**Post date:** [January 28, 2024, 2:48am UTC](https://discourse.julialang.org/t/eval-scope-problem-and-println-problem-for-multithreading/109333/11 "2024-01-28T02:48:24Z")

</div>

Thanks for your reply. I have used `invokelatest` and changed the code as follows:

```julia
using Sockets

# server
server = listen(2000)
errormonitor(
  @async begin
    sock = accept(server)
    ex = quote my() = println("aa") end
    errormonitor(@async invokelatest(Core.eval, Main, ex))
    println("bb")
    errormonitor(@async invokelatest(Core.eval, Main, Meta.parse("my()")))
    sleep(1)
  end
)

# client
socket = connect(2000)

```

As pointed out in other posts, if I run the code from a file `julia blah.jl`, then “aa” is not printed out.  
However, if I run the code from the REPL `julia> include("blah.jl")`, then “aa” is printed. There is something wrong when running from a file.

---

<div class="post-metadata">

**Author:** ![ccestbon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ccestbon/32/206575_2.png) [@ccestbon](https://discourse.julialang.org/u/ccestbon)\
**Post date:** [January 28, 2024, 8:20am UTC](https://discourse.julialang.org/t/eval-scope-problem-and-println-problem-for-multithreading/109333/12 "2024-01-28T08:20:10Z")

</div>

As pointed out by @Benny [post #13](https://discourse.julialang.org/t/eval-scope-problem-and-println-problem-for-multithreading/109333/13), it’s just the [script’s primary task ending and closing the process](https://stackoverflow.com/questions/34027380/julia-async-block-couldnt-get-any-result-with-command-prompt) when the `@async` task yielded control midway. Therefore, we can use `wait` or `@sync begin` to avoid the problem.

Therefore, I modified the code as follows by adding `wait`:

```julia
using Sockets

# server
server = listen(2000)
t =
  @async begin
    sock = accept(server)
    ex = quote
      function my()
        println("aa")
      end
    end
    errormonitor(@async invokelatest(Core.eval, Main, ex))
    println("bb")
    errormonitor(@async invokelatest(Core.eval, Main, Meta.parse("my()")))
  end

# client
socket = connect(2000)

wait(t)

```

By using `wait`, I get the same result for both `julia blah.jl` and `julia> include("blah.jl")`, i.e., “bb” and “aa” are both printed out.

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [January 28, 2024, 9:00am UTC](https://discourse.julialang.org/t/eval-scope-problem-and-println-problem-for-multithreading/109333/13 "2024-01-28T09:00:53Z")

</div>

I don’t think it’s `println`’s nested locks causing “aa” not to be printed at all; locking would affect task printing order. It’s just your [script’s primary task ending and closing the process](https://stackoverflow.com/questions/34027380/julia-async-block-couldnt-get-any-result-with-command-prompt) when your `@async` task yielded control midway. That’s just something you always need to account for when you run a script from the command line. I think enclosing the tasks in [`@sync begin ... end`](https://docs.julialang.org/en/v1/base/parallel/#Base.@sync) would work as well as `wait`, and it’s more convenient to do once over multiple tasks.

---

<div class="post-metadata">

**Author:** ![ccestbon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ccestbon/32/206575_2.png) [@ccestbon](https://discourse.julialang.org/u/ccestbon)\
**Post date:** [January 28, 2024, 9:17am UTC](https://discourse.julialang.org/t/eval-scope-problem-and-println-problem-for-multithreading/109333/14 "2024-01-28T09:17:55Z")

</div>

Thanks for your reply. Yes, your comment makes sense.
