41 lines
1.2 KiB
Elixir
41 lines
1.2 KiB
Elixir
# Implement error_handler pattern for Erlang
|
|
# which is integrated with Kernel.ParallelCompiler
|
|
defmodule Kernel.ErrorHandler do
|
|
@moduledoc false
|
|
|
|
def undefined_function(module, fun, args) do
|
|
ensure_loaded(module)
|
|
:error_handler.undefined_function(module, fun, args)
|
|
end
|
|
|
|
def undefined_lambda(module, fun, args) do
|
|
ensure_loaded(module)
|
|
:error_handler.undefined_lambda(module, fun, args)
|
|
end
|
|
|
|
def release() do
|
|
# On release, no longer allow elixir_ensure_compiled
|
|
# directives and revert to the original error handler.
|
|
# Note we should not delete the elixir_compiler_pid though,
|
|
# as we still want to send notifications to the compiler.
|
|
:erlang.erase(:elixir_ensure_compiled)
|
|
:erlang.process_flag(:error_handler, :error_handler)
|
|
:ok
|
|
end
|
|
|
|
defp ensure_loaded(module) do
|
|
case Code.ensure_loaded(module) do
|
|
{:module, _} -> :ok
|
|
{:error, _} ->
|
|
parent = :erlang.get(:elixir_compiler_pid)
|
|
ref = :erlang.make_ref
|
|
send parent, {:waiting, :module, self(), ref, module}
|
|
:erlang.garbage_collect(self)
|
|
receive do
|
|
{^ref, :ready} -> :ok
|
|
{^ref, :release} -> release()
|
|
end
|
|
end
|
|
end
|
|
end
|