# Yield(), tasks and interrupting OpenGL code

**URL:** <https://discourse.julialang.org/t/yield-tasks-and-interrupting-opengl-code/14085>\
**Category:** General Usage\
**Tags:** question\
**Created:** [August 26, 2018, 3:11pm UTC](https://discourse.julialang.org/t/yield-tasks-and-interrupting-opengl-code/14085 "2018-08-26T15:11:11Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![davidm](https://avatars.discourse-cdn.com/v4/letter/d/71e660/32.png) [@davidm](https://discourse.julialang.org/u/davidm)\
**Post date:** [August 26, 2018, 3:11pm UTC](https://discourse.julialang.org/t/yield-tasks-and-interrupting-opengl-code/14085/1 "2018-08-26T15:11:11Z")

</div>

I’ve been trying to work with OpenGL (ModernGL.jl) within the REPL but using a scheduled task to keep rendering continuously to allow interactivity with `schedule(Task(renderLoop))`.

I experienced some crashes (difficult to reproduce these) and some OpenGL errors (easy to reproduce since they always happens when I follow the same steps).

After some debugging I think the problem happens because the OpenGL code I put in the REPL is interrupted by the `renderLoop` function that is in the scheduled task. Due to the nature of OpenGL it is not safe to interrupt blocks of OpenGL code to call other OpenGL code and I can confirm that that the scheduled task executed some instructions in the middle of the REPL code.

Of course, I don’t expect that multiple sentences in the REPL code are gonna make the scheduled task wait, but I did expect to don’t see a function call in the REPL being interrupted by the scheduled task.

I “saw” the interruption when the REPL code executed prints or the C function `glXGetProcAddress`.

My questions are: Seems my guess correct? is this expected behavior? Calls to `println` and `ccall` call `yield()`? Should this be documented?

If my problem is not very clear I can create and paste here the real code, but I hope some pseudocode is enough:

```julia
initialize_opengl()
flag = false

function renderLoop()
  global flag
  opengl_code()
  yield() # this is a safe point for executing other OpenGL code
  if flag
    @error "We are interrupting external OpenGL code, UNSAFE!!!"
  end
end

function extra_stuff()
  global flag
  flag=true
  # OpenGL code that mustn't be interrupted by other OpenGL code
  flag=false
end

julia> schedule(Task(renderLoop))

julia> extra_stuff()
Error: We are interrupting external OpenGL code, UNSAFE!!!

```

Context:  
I’m using Linux with Julia 1.0.0, I’m completely new to Julia but not so much to OpenGL.

Thank you! Issues aside, I’m having a great time learning and programming in Julia

---

<div class="post-metadata">

**Author:** ![tobias.knopp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tobias.knopp/32/7551_2.png) [@tobias.knopp](https://discourse.julialang.org/u/tobias.knopp)\
**Post date:** [August 26, 2018, 3:34pm UTC](https://discourse.julialang.org/t/yield-tasks-and-interrupting-opengl-code/14085/2 "2018-08-26T15:34:17Z")

</div>

I think (but @jameson knows better) that this is [Segfault when linking Scale widget with Entry · Issue #161 · JuliaGraphics/Gtk.jl · GitHub](https://github.com/JuliaGraphics/Gtk.jl/issues/161)

@jameson developed a macro for Gtk.jl that handles this (`Gtk.@sigatom`).  
[https://github.com/JuliaLang/julia/pull/13099](https://github.com/JuliaLang/julia/pull/13099) is supposed to fix the real issue.

---

<div class="post-metadata">

**Author:** ![davidm](https://avatars.discourse-cdn.com/v4/letter/d/71e660/32.png) [@davidm](https://discourse.julialang.org/u/davidm)\
**Post date:** [August 26, 2018, 8:53pm UTC](https://discourse.julialang.org/t/yield-tasks-and-interrupting-opengl-code/14085/3 "2018-08-26T20:53:52Z")

</div>

So, is it expected to see the task switching (yield of the `extra_stuff()`)?

Maybe the crashes were produced by the stack issue, although I don’t understand much this.

However, I don’t think the behavior I’m seeing with the flag and the `@error` has something to do with the stack. I think this can just be explained by hidden yields. But, of course, I’d be much happier if someone could confirm this.

---

<div class="post-metadata">

**Author:** ![jameson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jameson/32/23_2.png) [@jameson](https://discourse.julialang.org/u/jameson)\
**Post date:** [August 27, 2018, 2:13am UTC](https://discourse.julialang.org/t/yield-tasks-and-interrupting-opengl-code/14085/4 "2018-08-27T02:13:37Z")

</div>

You should treat Tasks as-if they are being run on different threads, so the usual provisions apply: use locks around critical regions, avoid race conditions, etc.  
I made `sigatom` (and its pair `siginterruptable`) in Gtk for convenience at marking critical regions—it just de-sugars to a `do`-block call to acquire and release the relevant lock.

---

<div class="post-metadata">

**Author:** ![ssfrr](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ssfrr/32/3736_2.png) [@ssfrr](https://discourse.julialang.org/u/ssfrr)\
**Post date:** [August 27, 2018, 3:09am UTC](https://discourse.julialang.org/t/yield-tasks-and-interrupting-opengl-code/14085/5 "2018-08-27T03:09:44Z")

</div>

To add to this, and more specifically address you question about whether this is expected - Julia tasks will generally yield on any I/O operation (printing to `STDOUT`, reading/writing from disk, etc.) but also any time someone’s code calls `wait` on a `Condition`. In general you don’t know whether some code you’re calling is going to do something that yields.

---

<div class="post-metadata">

**Author:** ![davidm](https://avatars.discourse-cdn.com/v4/letter/d/71e660/32.png) [@davidm](https://discourse.julialang.org/u/davidm)\
**Post date:** [August 27, 2018, 7:41pm UTC](https://discourse.julialang.org/t/yield-tasks-and-interrupting-opengl-code/14085/6 "2018-08-27T19:41:29Z")

</div>

I see, I didn’t know about the automatic yielding. I understand the model is similar to Go’s one.

I tried to use a `Threads.Mutex` to fix it, but I wasn’t able to make it work. I tried to make the code smaller and I ended up with this:

```julia
mutex = Threads.Mutex()

function f()
   global mutex
   lock(mutex)
   println("locked")
   i=0
   while true
       i=i+1
       yield()
   end
end

schedule(Task(f))

yield()
lock(mutex)
println("hello")
unlock(mutex)

```

This outputs:

```julia
locked
hello

```

Which for me doesn’t make any sense since the mutex is locked on `f` as shown with the “locked” print. I expected to see the main task blocked forever and no “hello” in the output.

Thank you all!

---

<div class="post-metadata">

**Author:** ![davidm](https://avatars.discourse-cdn.com/v4/letter/d/71e660/32.png) [@davidm](https://discourse.julialang.org/u/davidm)\
**Post date:** [August 28, 2018, 9:45pm UTC](https://discourse.julialang.org/t/yield-tasks-and-interrupting-opengl-code/14085/7 "2018-08-28T21:45:17Z")

</div>

Ok, I found the problem. I was using a `Threads.Mutex` but that cover different threads but not different tasks within the same thread (which seems very odd to me).

Replacing it by a `ReentrantLock` fixed everything, although it clearly states that is not thread-safe.

I don’t care much right now, but I think that having a Lock that actually acquires the mutex per task while being thread-safe is super useful.

I’m probably too inexperienced in Julia for this, but I could to try to push this. Do you think it makes sense to add that new lock? What would be the next steps, opening an issue in github, creating a PR?
