From 659d15d2a51781be3ad16ce1c42682068b4f4966 Mon Sep 17 00:00:00 2001 From: Vince Foley <39946+binaryseed@users.noreply.github.com> Date: Fri, 26 Mar 2021 16:30:08 -0700 Subject: [PATCH] Better solve deadlocks on Elixir v1.12+ (#1057) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Better solve deadlocks on Elixir v1.12+ Closes #937. * Update type_imports.ex * Silence dialyzer error Co-authored-by: José Valim --- lib/absinthe/phase/schema/type_imports.ex | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/lib/absinthe/phase/schema/type_imports.ex b/lib/absinthe/phase/schema/type_imports.ex index 48d389e2e8..04e14e7ee7 100644 --- a/lib/absinthe/phase/schema/type_imports.ex +++ b/lib/absinthe/phase/schema/type_imports.ex @@ -33,7 +33,7 @@ defmodule Absinthe.Phase.Schema.TypeImports do end defp do_imports([{module, opts} | rest], acc, schema) do - case Code.ensure_compiled(module) do + case ensure_compiled(module) do {:module, module} -> [other_def] = module.__absinthe_blueprint__.schema_definitions @@ -58,6 +58,21 @@ defmodule Absinthe.Phase.Schema.TypeImports do end end + # Elixir v1.12 includes a Code.ensure_compiled!/1 that tells + # the compiler it should only continue if the module is available. + # This gives the Elixir compiler more information to address + # deadlocks. + # TODO: Remove the else clause once we require Elixir v1.12+. + @compile {:no_warn_undefined, {Code, :ensure_compiled!, 1}} + @dialyzer {:nowarn_function, [ensure_compiled: 1]} + defp ensure_compiled(module) do + if function_exported?(Code, :ensure_compiled!, 1) do + {:module, Code.ensure_compiled!(module)} + else + Code.ensure_compiled(module) + end + end + # Generate an error when loading module fails @spec error(module :: module(), error :: :embedded | :badfile | :nofile | :on_load_failure) :: Absinthe.Phase.Error.t()