# How to stop a thread blocked by readline?

**URL:** <https://discourse.julialang.org/t/how-to-stop-a-thread-blocked-by-readline/56262>\
**Category:** General Usage\
**Tags:** question, multithreading\
**Created:** [March 1, 2021, 4:15pm UTC](https://discourse.julialang.org/t/how-to-stop-a-thread-blocked-by-readline/56262 "2021-03-01T16:15:49Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![Impressium](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/impressium/32/19575_2.png) [@Impressium](https://discourse.julialang.org/u/Impressium)\
**Post date:** [March 1, 2021, 4:15pm UTC](https://discourse.julialang.org/t/how-to-stop-a-thread-blocked-by-readline/56262/1 "2021-03-01T16:15:49Z")

</div>

Hey all 🙂

I want to use a thread redirecting `stderr`. The thread should stop after a `Threads.Atomic` is set to `false`.

My current example is blocked on `readline` and stops only after something is written to it. Is there a way to stop the thread immediately?

Here is my little example:

```julia
julia> (w, r) = redirect_stderr()
(Base.PipeEndpoint(Base.Libc.WindowsRawSocket(0x000000000000bdf0) open, 0 bytes waiting), Base.PipeEndpoint(Base.Libc.WindowsRawSocket(0x000000000000bd14) open, 0 bytes waiting))

julia> IS_RUNNING = Threads.Atomic{Bool}(true)
Base.Threads.Atomic{Bool}(true)

julia> t = @async while IS_RUNNING[]
           line = readline(w)
           println(line)
       end
Task (runnable) @0x00000000437d73d0

julia> println(stderr, "Error")
Error

julia> IS_RUNNING[] = false;

julia> t |> istaskdone
false

```

Thanks

---

<div class="post-metadata">

**Author:** ![pixel27](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pixel27/32/8902_2.png) [@pixel27](https://discourse.julialang.org/u/pixel27)\
**Post date:** [March 2, 2021, 4:12am UTC](https://discourse.julialang.org/t/how-to-stop-a-thread-blocked-by-readline/56262/2 "2021-03-02T04:12:12Z")

</div>

The only way I know how would be to `close(w)`. When the IO is closed readline will throw an exception I believe.

---

<div class="post-metadata">

**Author:** ![pbayer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pbayer/32/11675_2.png) [@pbayer](https://discourse.julialang.org/u/pbayer)\
**Post date:** [March 2, 2021, 8:31am UTC](https://discourse.julialang.org/t/how-to-stop-a-thread-blocked-by-readline/56262/3 "2021-03-02T08:31:43Z")

</div>

I propose the following function:

```julia
function switch(s)
    if s == :on
        doit[1] = true
        rd = redirect_stderr()[1]
        @async while doit[1]
            println("Test: ", readline(rd))
        end
    elseif s == :off
        doit[1] = false
        println(stderr, s) # solution: give it something to read !!
        redirect_stderr(old_stderr)
    else
        println(stderr, "not allowed: $s")
    end
end

```

then you can do (needs still 2 global variables):

```julia
julia> old_stderr = stderr
Base.TTY(RawFD(22) open, 0 bytes waiting)

julia> doit = [false];

julia> t = switch(:on)
Task (runnable) @0x000000016704f860

julia> println(stderr, "test 1")
Test: test 1

julia> println(stderr, "test 2")
Test: test 2

julia> switch(:off)
Test: off
Base.TTY(RawFD(22) open, 0 bytes waiting)

julia> println(stderr, "test 3")
test 3

julia> t
Task (done) @0x000000016704f860

```

---

<div class="post-metadata">

**Author:** ![pbayer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pbayer/32/11675_2.png) [@pbayer](https://discourse.julialang.org/u/pbayer)\
**Post date:** [March 2, 2021, 11:03am UTC](https://discourse.julialang.org/t/how-to-stop-a-thread-blocked-by-readline/56262/4 "2021-03-02T11:03:52Z")

</div>

This can be simplified to:

```julia
function switch2(s)
    my_switch = "sloBMBS90eXNG"
    if s == :on
        rd = redirect_stderr()[1]
        @async while true
            line = readline(rd)
            line != my_switch ? println("Test2: ", line) : break
        end
    elseif s == :off
        println(stderr, my_switch)
        redirect_stderr(old_stderr)
    else
        println(stderr, "not allowed: $s")
    end
end

julia> t = switch2(:on)
Task (runnable) @0x00000001671baba0

julia> println(stderr, "test 1")
Test2: test 1

julia> switch2(:off)
Base.TTY(RawFD(22) open, 0 bytes waiting)

julia> println(stderr, "test 2")
test 2

julia> t
Task (done) @0x00000001671baba0

```

only the `old_stderr` is needed as a global variable to restore `stderr`.

---

<div class="post-metadata">

**Author:** ![pbayer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pbayer/32/11675_2.png) [@pbayer](https://discourse.julialang.org/u/pbayer)\
**Post date:** [March 2, 2021, 11:37am UTC](https://discourse.julialang.org/t/how-to-stop-a-thread-blocked-by-readline/56262/5 "2021-03-02T11:37:34Z")

</div>

the following doesn’t need even global `old_stderr`. We capture `stderr` when we switch on and let the task itself restore it.

```julia
function switch3(s)
    my_switch = "sloBMBS90eXNG"
    if s == :on
        if stderr isa Base.TTY
            old_stderr = stderr
            rd = redirect_stderr()[1]
            @async while true
                line = readline(rd)
                line != my_switch ? 
                    println("Test3: ", line) : 
                    (redirect_stderr(old_stderr); break)
            end
        end
    elseif s == :off
        println(stderr, my_switch)
    else
        println(stderr, "not allowed: $s")
    end
end

julia> t = switch3(:on)
Task (runnable) @0x000000011331f640

julia> println(stderr, "test 1")
Test3: test 1

julia> switch3(:off)

julia> println(stderr, "test 2")
test 2

julia> t
Task (done) @0x000000011331f640

```

> [@Impressium](#):
>
> Is there a way to stop the thread immediately?

That should be fine now. What do you think?
