# Task switch not allowed from inside staged nor pure functions

**URL:** <https://discourse.julialang.org/t/task-switch-not-allowed-from-inside-staged-nor-pure-functions/20488>\
**Category:** General Usage\
**Tags:** question\
**Created:** [February 5, 2019, 9:35pm UTC](https://discourse.julialang.org/t/task-switch-not-allowed-from-inside-staged-nor-pure-functions/20488 "2019-02-05T21:35:55Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![chakravala](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chakravala/32/6832_2.png) [@chakravala](https://discourse.julialang.org/u/chakravala)\
**Post date:** [February 5, 2019, 9:35pm UTC](https://discourse.julialang.org/t/task-switch-not-allowed-from-inside-staged-nor-pure-functions/20488/1 "2019-02-05T21:35:55Z")

</div>

Recently I encountered the following error while developing my experimental [Grassmann.jl](https://github.com/chakravala/Grassmann.jl) package

The following error only occurs if I run the commands at once using `;` on one line

```nohighlight
julia> using Grassmann; mixedbasis"2"
[ Info: Allocating thread-safe 16×Basis{VectorSpace{4,0,0,12}*,...}
┌ Error: Exception while generating log record in module Grassmann at /home/flow/.julia/dev/Grassmann/src/Grassmann.jl:136
│ exception =
│ task switch not allowed from inside staged nor pure functions
│ Stacktrace:
│ [1] unsafe_write(::Base.TTY, ::Ptr{UInt8}, ::UInt64) at ./stream.jl:830
│ [2] macro expansion at ./io.jl:509 [inlined]
│ [3] write(::Base.TTY, ::Array{UInt8,1}) at ./io.jl:532
│ [4] #handle_message#2(::Nothing, ::Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}, ::Function, ::Logging.ConsoleLogger, ::Base.CoreLogging.LogLevel, ::String, ::Module, ::String, ::Symbol, ::String, ::Int64) at /build/julia/src/julia-1.0.3/usr/share/julia/stdlib/v1.0/Logging/src/ConsoleLogger.jl:161
│ [5] handle_message(::Logging.ConsoleLogger, ::Base.CoreLogging.LogLevel, ::String, ::Module, ::String, ::Symbol, ::String, ::Int64) at /build/julia/src/julia-1.0.3/usr/share/julia/stdlib/v1.0/Logging/src/ConsoleLogger.jl:100
│ [6] getalgebra(::Int64, ::Int64, ::UInt64) at ./logging.jl:320
│ [7] @mixedbasis_str(::LineNumberNode, ::Module, ::Any) at /home/flow/.julia/dev/Grassmann/src/multivectors.jl:212
└ @ Grassmann ~/.julia/dev/Grassmann/src/Grassmann.jl:136
Exception handling log message: 
(++--*, v, v₁, v₂, w¹, w², v₁₂, v₁w¹, v₁w², v₂w¹, v₂w², w¹², v₁₂w¹, v₁₂w², v₁w¹², v₂w¹², v₁₂w¹²)

```

otherwise, if I first run `using Grassmann` and then `mixedbasis"2"` afterwards, there is no issue.

This is likely because the REPL is doing some task switching due to the combined input.

What can I do about this issue? As far as I can tell, the error message does not affect the actual Julia session, and the result of the `mixedbasis"2"` command is returned after the error message.

This is an error which only takes place in some other REPL scope, but not in the program execution.

Now, I know some people might suggest that I should not be using `@pure` methods in certain contexts; however, I am having success with them if they are used safely. It is my choice to work with it and I don’t intend to change my design currently only to solve this one particular case.

Is there some way to disable the logging which causes this error? What’s exactly going on here, would be useful to know more details about how the error occurs.

---

<div class="post-metadata">

**Author:** ![tkoolen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkoolen/32/1603_2.png) [@tkoolen](https://discourse.julialang.org/u/tkoolen)\
**Post date:** [February 5, 2019, 9:56pm UTC](https://discourse.julialang.org/t/task-switch-not-allowed-from-inside-staged-nor-pure-functions/20488/2 "2019-02-05T21:56:24Z")

</div>

`@pure` functions may not have side effects. Printing a log message most certainly counts as a side effect. Either don’t declare the function `@pure` or remove the log message.

---

<div class="post-metadata">

**Author:** ![chakravala](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chakravala/32/6832_2.png) [@chakravala](https://discourse.julialang.org/u/chakravala)\
**Post date:** [February 5, 2019, 9:57pm UTC](https://discourse.julialang.org/t/task-switch-not-allowed-from-inside-staged-nor-pure-functions/20488/3 "2019-02-05T21:57:36Z")

</div>

I didn’t use any log messages, they are from the REPL internals I believe

as I said, there is no error if the commands are entered separately

```nohighlight
julia> using Grassmann

julia> mixedbasis"2"

```

---

<div class="post-metadata">

**Author:** ![bennedich](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bennedich/32/4894_2.png) [@bennedich](https://discourse.julialang.org/u/bennedich)\
**Post date:** [February 5, 2019, 9:58pm UTC](https://discourse.julialang.org/t/task-switch-not-allowed-from-inside-staged-nor-pure-functions/20488/4 "2019-02-05T21:58:59Z")

</div>

> [@chakravala](#):
>
> I know some people might suggest that I should not be using `@pure` methods in certain contexts; however, I am having success with them if they are used safely. It is my choice to work with it

In a [recent topic](https://discourse.julialang.org/t/mutable-struct-vs-closure/20233/60), several posters warned you that your “pure” code was in fact not pure, and that you shouldn’t declare it such… It’s your choice to work with it, but consider that users of your package will have no choice but to work with it too (with issues like this).

> [@chakravala](#):
>
> Is there some way to disable the logging which causes this error?

> [@chakravala](#):
>
> I didn’t use any log messages

Hmm, is it not the `@info` statement at Grassmann.jl:136 that triggers this? Could you wrap that in a try/catch? (or remove it/move it outside the pure function, as @tkoolen suggests)

---

<div class="post-metadata">

**Author:** ![chakravala](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chakravala/32/6832_2.png) [@chakravala](https://discourse.julialang.org/u/chakravala)\
**Post date:** [February 5, 2019, 10:00pm UTC](https://discourse.julialang.org/t/task-switch-not-allowed-from-inside-staged-nor-pure-functions/20488/5 "2019-02-05T22:00:42Z")

</div>

> [@bennedich](#):
>
> Hmm, is it not the `@info` statement at Grassmann.jl:136 that triggers this? Could you wrap that in a try/catch? (or remove it/move it outside the pure function, as @tkoolen suggests)

Thanks, you’re right. Yea, I might just remove the entire message I suppose, unless there is some way of detecting this situation and turning it off

> [@bennedich](#):
>
> In a [recent topic](https://discourse.julialang.org/t/mutable-struct-vs-closure/20233/60), several posters warned you that your “pure” code was in fact not pure, and that you shouldn’t declare it such… It’s your choice to work with it, but consider that users of your package will have no choice but to work with it too (with issues like this).

This package is for my own personal enjoyment and explorations, but I hope that it can be useful for other people too. If people encounter a specific issue, they should let me know.

---

<div class="post-metadata">

**Author:** ![tkf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkf/32/17635_2.png) [@tkf](https://discourse.julialang.org/u/tkf)\
**Post date:** [February 5, 2019, 10:14pm UTC](https://discourse.julialang.org/t/task-switch-not-allowed-from-inside-staged-nor-pure-functions/20488/6 "2019-02-05T22:14:23Z")

</div>

I know that `Core.print` can be used in generated function. Not sure if you can use it inside `@pure` though. But I guess this is only for debugging, not for messaging in in-production packages.

---

<div class="post-metadata">

**Author:** ![chakravala](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chakravala/32/6832_2.png) [@chakravala](https://discourse.julialang.org/u/chakravala)\
**Post date:** [February 5, 2019, 10:20pm UTC](https://discourse.julialang.org/t/task-switch-not-allowed-from-inside-staged-nor-pure-functions/20488/7 "2019-02-05T22:20:02Z")

</div>

Alright, just pushed the commit and removed the `@info` logging message that I had.

This is actually the best option, now you can use `Base.Threads.@threads` without calling first

```nohighlight
julia> using Grassmann

julia> out = Array{Any,1}(undef,7);

julia> Base.Threads.@threads for i ∈ 1:7
           out[i] = Λ(7)[i]
       end

julia> out
7-element Array{Any,1}:
 v 
 v₁
 v₂
 v₃
 v₄
 v₅
 v₆

```

As you can see, it is no longer necessary to call the function before multithreading it. You can just simply run a multithreaded call without problem, since the `@info` is now removed.

This means that the `@info` message itself is no longer necessary, because the algebra does not need to be declared thread safe to the user anymore, because it is thread safe. How ironic.

Thanks for the suggestions.

---

<div class="post-metadata">

**Author:** ![c42f](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/c42f/32/52842_2.png) [@c42f](https://discourse.julialang.org/u/c42f)\
**Post date:** [February 6, 2019, 2:20am UTC](https://discourse.julialang.org/t/task-switch-not-allowed-from-inside-staged-nor-pure-functions/20488/8 "2019-02-06T02:20:24Z")

</div>

I still think it would be cool and extremely useful to arrange `@info` and other logging so that it’s useful in restricted contexts like generated functions and finalizers. I think this would require some internal changes and might come with restrictions, but it would be ever so handy.

One way to preserve most of the semantics might be to have a (circular?) buffer of pending log events and a way to empty the buffer on leaving the restricted context. It seems kind of tricky but doable.

---

<div class="post-metadata">

**Author:** ![maleadt](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/maleadt/32/10097_2.png) [@maleadt](https://discourse.julialang.org/u/maleadt)\
**Post date:** [February 6, 2019, 9:33am UTC](https://discourse.julialang.org/t/task-switch-not-allowed-from-inside-staged-nor-pure-functions/20488/9 "2019-02-06T09:33:54Z")

</div>

> [@c42f](#):
>
> I still think it would be cool and extremely useful to arrange `@info` and other logging so that it’s useful in restricted contexts like generated functions and finalizers. I think this would require some internal changes and might come with restrictions, but it would be ever so handy.

I’ve used this in the past:

```julia
using Logging

# define safe loggers for use in generated functions (where task switches are not allowed)
for level in [:debug, :info, :warn, :error]
    @eval begin
        macro $(Symbol("safe_$level"))(ex...)
            macrocall = :(@placeholder $(ex...))
            # NOTE: `@placeholder` in order to avoid hard-coding @ __LINE__ etc
            macrocall.args[1] = Symbol($"@$level")
            quote
                old_logger = global_logger()
                global_logger(Logging.ConsoleLogger(Core.stderr, old_logger.min_level))
                ret = $(esc(macrocall))
                global_logger(old_logger)
                ret
            end
        end
    end
end

```

---

<div class="post-metadata">

**Author:** ![c42f](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/c42f/32/52842_2.png) [@c42f](https://discourse.julialang.org/u/c42f)\
**Post date:** [February 6, 2019, 10:12am UTC](https://discourse.julialang.org/t/task-switch-not-allowed-from-inside-staged-nor-pure-functions/20488/10 "2019-02-06T10:12:06Z")

</div>

Hah thanks, that looks handy (if evil :-D)
