diff --git a/lib/mix/lib/mix/sync/lock.ex b/lib/mix/lib/mix/sync/lock.ex index 17a970c1cc..a9ecfc9fc4 100644 --- a/lib/mix/lib/mix/sync/lock.ex +++ b/lib/mix/lib/mix/sync/lock.ex @@ -72,7 +72,6 @@ defmodule Mix.Sync.Lock do @probe_data "mixlock" @probe_data_size byte_size(@probe_data) @probe_timeout_ms 5_000 - @version 2 @typedoc """ Options for `with_lock/3`. @@ -132,12 +131,7 @@ defmodule Mix.Sync.Lock do defp base_path do # We include user in the dir to avoid permission conflicts across users - user = System.get_env("USER", "default") - - Path.join( - System.tmp_dir!(), - "mix_lock_#{@version}_#{Base.url_encode64(user, padding: false)}" - ) + Path.join(System.tmp_dir!(), "mix_lock_user#{Mix.Utils.detect_user_id!()}") end defp lock_disabled?(), do: System.get_env("MIX_OS_CONCURRENCY_LOCK") in ~w(0 false) diff --git a/lib/mix/lib/mix/sync/pubsub.ex b/lib/mix/lib/mix/sync/pubsub.ex index 00ad2ad492..db6a23a99c 100644 --- a/lib/mix/lib/mix/sync/pubsub.ex +++ b/lib/mix/lib/mix/sync/pubsub.ex @@ -282,8 +282,7 @@ defmodule Mix.Sync.PubSub do defp base_path do # We include user in the dir to avoid permission conflicts across users - user = System.get_env("USER", "default") - Path.join(System.tmp_dir!(), "mix_pubsub_#{Base.url_encode64(user, padding: false)}") + Path.join(System.tmp_dir!(), "mix_pubsub_user#{Mix.Utils.detect_user_id!()}") end defp recv(socket, size, timeout \\ :infinity) do diff --git a/lib/mix/lib/mix/utils.ex b/lib/mix/lib/mix/utils.ex index b1f9d561f3..c8a5cf6730 100644 --- a/lib/mix/lib/mix/utils.ex +++ b/lib/mix/lib/mix/utils.ex @@ -900,4 +900,37 @@ defmodule Mix.Utils do [proxy_auth: {user, pass}] end + + @doc """ + Returns the user id of the currently running process. + + The user id is obtained by creating a temporary file and checking + it's UID. Note that the UID may be `nil` on non-Unix systems. + """ + def detect_user_id!() do + case Mix.State.fetch(:user_id) do + {:ok, uid} -> + uid + + :error -> + dir = System.tmp_dir!() + File.mkdir_p!(dir) + rand = :crypto.strong_rand_bytes(3) |> Base.url_encode64() + path = Path.join(dir, "mix_user_check_#{System.os_time()}_#{rand}") + + uid = + try do + File.touch!(path) + File.stat!(path) + else + %{uid: :undefined} -> nil + %{uid: uid} -> uid + after + File.rm(path) + end + + Mix.State.put(:user_id, uid) + uid + end + end end