Skip to content

Commit 48478fc

Browse files
committed
Display a warning when dune builds via RPC
When an instance of dune is already running, invoking `dune build` will still build the target, howwever other command line arguments are silently ignored by dune as the current RPC interface is too limited to express them. This may change over time, but currently it's unusual UX for `dune build` to behave differently depending on whether or not another instance of `dune build` is already running. To more accurately set user expectations, print a warning when dune is running with this reduced functionality. Signed-off-by: Stephen Sherratt <[email protected]>
1 parent bd1d76b commit 48478fc

File tree

4 files changed

+49
-14
lines changed

4 files changed

+49
-14
lines changed

bin/build_cmd.ml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ let build =
207207
state of the lock could otherwise change between checking it and taking
208208
it. *)
209209
match Dune_util.Global_lock.lock ~timeout:None with
210-
| Error () ->
210+
| Error lock_held_by ->
211211
(* This case is reached if dune detects that another instance of dune
212212
is already running. Rather than performing the build itself, the
213213
current instance of dune will instruct the already-running instance to
@@ -217,6 +217,12 @@ let build =
217217
perform the RPC call.
218218
*)
219219
Scheduler.go_without_rpc_server ~common ~config (fun () ->
220+
User_warning.emit
221+
[ Dune_util.Global_lock.Lock_held_by.message lock_held_by
222+
; Pp.text
223+
"The requested targets will still be built however functionality will be \
224+
reduced and some command line arguments will be ignored."
225+
];
220226
build_via_rpc_server targets)
221227
| Ok () ->
222228
let request setup =

src/dune_util/global_lock.ml

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,28 @@ end
6666

6767
let locked = ref false
6868

69+
module Lock_held_by = struct
70+
type t =
71+
| Pid_from_lockfile of string
72+
| Unknown
73+
74+
let read_lock_file () =
75+
match Io.read_file (Path.build lock_file) with
76+
| exception _ -> Unknown
77+
| pid -> Pid_from_lockfile pid
78+
;;
79+
80+
let message t =
81+
Pp.textf
82+
"A running dune%s instance has locked the build directory. If this is not the \
83+
case, please delete %S."
84+
(match t with
85+
| Unknown -> ""
86+
| Pid_from_lockfile pid -> sprintf " (pid: %s)" pid)
87+
(Path.Build.to_string_maybe_quoted lock_file)
88+
;;
89+
end
90+
6991
let lock ~timeout =
7092
match Config.(get global_lock) with
7193
| `Disabled -> Ok ()
@@ -90,22 +112,15 @@ let lock ~timeout =
90112
| `Success ->
91113
locked := true;
92114
Ok ()
93-
| `Failure -> Error ())
115+
| `Failure ->
116+
let lock_held_by = Lock_held_by.read_lock_file () in
117+
Error lock_held_by)
94118
;;
95119

96120
let lock_exn ~timeout =
97121
match lock ~timeout with
98122
| Ok () -> ()
99-
| Error () ->
100-
User_error.raise
101-
[ Pp.textf
102-
"A running dune%s instance has locked the build directory. If this is not the \
103-
case, please delete %s"
104-
(match Io.read_file (Path.build lock_file) with
105-
| exception _ -> ""
106-
| pid -> sprintf " (pid: %s)" pid)
107-
(Path.Build.to_string_maybe_quoted lock_file)
108-
]
123+
| Error lock_held_by -> User_error.raise [ Lock_held_by.message lock_held_by ]
109124
;;
110125

111126
let unlock () =

src/dune_util/global_lock.mli

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,16 @@
22
33
Before starting rpc, writing to the build dir, this lock should be locked. *)
44

5-
(** attempt to acquire a lock. once a lock is locked, subsequent locks always
5+
module Lock_held_by : sig
6+
type t
7+
8+
val message : t -> 'a Pp.t
9+
end
10+
11+
(** Attempt to acquire a lock. once a lock is locked, subsequent locks always
612
succeed. Returns [Ok ()] if the lock is acquired within [timeout] seconds,
713
and [Error ()] otherwise. *)
8-
val lock : timeout:float option -> (unit, unit) result
14+
val lock : timeout:float option -> (unit, Lock_held_by.t) result
915

1016
val lock_exn : timeout:float option -> unit
1117

test/blackbox-tests/test-cases/watching/watching-eager-concurrent-build-command.t

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,20 @@ Build the project once before starting the watch server so the watch server star
2424

2525
Demonstrate that we can run "dune build" while the watch server is running.
2626
$ dune build
27+
Warning: A running dune (pid: 124305) instance has locked the build
28+
directory. If this is not the case, please delete "_build/.lock".
29+
The requested targets will still be built however functionality will be
30+
reduced and some command line arguments will be ignored.
2731
Success
2832

2933
Demonstrate that error messages are still printed by "dune build" when it's
3034
acting as an RPC client while running concurrently with an RPC server.
3135
$ echo 'let () = print_endlin "Hello, World!"' > foo.ml
3236
$ dune build
37+
Warning: A running dune (pid: 124305) instance has locked the build
38+
directory. If this is not the case, please delete "_build/.lock".
39+
The requested targets will still be built however functionality will be
40+
reduced and some command line arguments will be ignored.
3341
File "$TESTCASE_ROOT/foo.ml", line 1, characters 9-21:
3442
1 | let () = print_endlin "Hello, World!"
3543
^^^^^^^^^^^^

0 commit comments

Comments
 (0)