From 105f697037d00743f3071e931c8b47bf8f0952c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20K=C5=82osko?= Date: Mon, 29 Sep 2025 23:39:05 +0200 Subject: [PATCH 1/3] Improve user detection in lock and pubsub implementation --- lib/mix/lib/mix/sync/lock.ex | 3 +-- lib/mix/lib/mix/sync/pubsub.ex | 3 +-- lib/mix/lib/mix/utils.ex | 23 +++++++++++++++++++++++ 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/lib/mix/lib/mix/sync/lock.ex b/lib/mix/lib/mix/sync/lock.ex index 9f13b853435..afe22f655d1 100644 --- a/lib/mix/lib/mix/sync/lock.ex +++ b/lib/mix/lib/mix/sync/lock.ex @@ -131,8 +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_#{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 00ad2ad4925..db6a23a99c7 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 b1f9d561f35..bb85762a488 100644 --- a/lib/mix/lib/mix/utils.ex +++ b/lib/mix/lib/mix/utils.ex @@ -900,4 +900,27 @@ 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 + dir = System.tmp_dir!() + File.mkdir_p!(dir) + + path = + Path.join(dir, "mix_user_check_#{System.os_time()}_#{System.unique_integer([:positive])}") + + File.touch!(path) + %{uid: uid} = File.stat!(path) + _ = File.rm(path) + + case uid do + :undefined -> nil + uid -> uid + end + end end From 7436f4672418b78feead9f98b6602b47c7d56e60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Tue, 30 Sep 2025 13:01:56 +0200 Subject: [PATCH 2/3] Update lib/mix/lib/mix/utils.ex --- lib/mix/lib/mix/utils.ex | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/lib/mix/lib/mix/utils.ex b/lib/mix/lib/mix/utils.ex index bb85762a488..56374a8b3ea 100644 --- a/lib/mix/lib/mix/utils.ex +++ b/lib/mix/lib/mix/utils.ex @@ -908,19 +908,29 @@ defmodule Mix.Utils do it's UID. Note that the UID may be `nil` on non-Unix systems. """ def detect_user_id!() do - dir = System.tmp_dir!() - File.mkdir_p!(dir) - - path = - Path.join(dir, "mix_user_check_#{System.os_time()}_#{System.unique_integer([:positive])}") - - File.touch!(path) - %{uid: uid} = File.stat!(path) - _ = File.rm(path) + 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 - case uid do - :undefined -> nil - uid -> uid + Mix.State.put(:user_id, uid) + uid end end end From 22cfac142f2b7e9be3d248b3604c6ee74df2b7d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Tue, 30 Sep 2025 13:14:56 +0200 Subject: [PATCH 3/3] Update lib/mix/lib/mix/utils.ex --- lib/mix/lib/mix/utils.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mix/lib/mix/utils.ex b/lib/mix/lib/mix/utils.ex index 56374a8b3ea..c8a5cf6730f 100644 --- a/lib/mix/lib/mix/utils.ex +++ b/lib/mix/lib/mix/utils.ex @@ -917,7 +917,7 @@ defmodule Mix.Utils do 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)