15
15
-- of the license. --
16
16
-- ----------------------------------------------------------------------------
17
17
18
+ with Ada.Exceptions ;
18
19
with Ada.Streams ;
20
+ with GNAT.Lock_Files ;
19
21
with GNAT.OS_Lib ;
20
22
with GNATCOLL.Traces ;
21
23
with GNATCOLL.VFS ;
@@ -42,7 +44,8 @@ package body LSP.Alire is
42
44
GNATCOLL_Tracers.Create (" ALS.ALIRE" , GNATCOLL.Traces.On);
43
45
44
46
Alire_Verbose : constant GNATCOLL_Tracers.Tracer :=
45
- GNATCOLL_Tracers.Create (" ALS.ALIRE.VERBOSE" , GNATCOLL.Traces.From_Config);
47
+ GNATCOLL_Tracers.Create
48
+ (" ALS.ALIRE.VERBOSE" , GNATCOLL.Traces.From_Config);
46
49
47
50
type Process_Listener is limited
48
51
new Spawn.Process_Listeners.Process_Listener
@@ -63,11 +66,31 @@ package body LSP.Alire is
63
66
overriding
64
67
procedure Error_Occurred (Self : in out Process_Listener; Error : Integer);
65
68
66
- procedure Start_Alire
69
+ procedure Start_Alire_Sync
67
70
(Options : VSS.String_Vectors.Virtual_String_Vector;
68
71
Root : String;
69
72
Error : out VSS.Strings.Virtual_String;
70
73
Lines : out VSS.String_Vectors.Virtual_String_Vector);
74
+ -- This procedure uses a cross-process lock based on the current directory
75
+ -- before starting Alire. This ensures that all ALS processes spawned in
76
+ -- the same directory make Alire invocations in sequence and not in
77
+ -- parallel, since concurrent Alire invocations on the same workspace can
78
+ -- clash with each other on shared temporary files.
79
+ --
80
+ -- The actual invocation of Alire is delegated to Start_Alire_Unsynced.
81
+ --
82
+ -- This is necessary in contexts where two ALS processes are spawned in the
83
+ -- same workspace, one acting as an Ada language server and the other
84
+ -- acting as a GPR language server. Both make Alire invocations to set up
85
+ -- the environment, hence the need for synchronization.
86
+
87
+ procedure Start_Alire_Unsynced
88
+ (Options : VSS.String_Vectors.Virtual_String_Vector;
89
+ Root : String;
90
+ Error : out VSS.Strings.Virtual_String;
91
+ Lines : out VSS.String_Vectors.Virtual_String_Vector);
92
+ -- This procedure starts Alire immediately with no synchronization
93
+ -- mechanism.
71
94
72
95
Anchored : constant VSS.Regular_Expressions.Match_Options :=
73
96
(VSS.Regular_Expressions.Anchored_Match => True);
@@ -103,7 +126,7 @@ package body LSP.Alire is
103
126
is
104
127
Lines : VSS.String_Vectors.Virtual_String_Vector;
105
128
begin
106
- Start_Alire
129
+ Start_Alire_Sync
107
130
(Options => [" --non-interactive" , " build" , " --stop-after=generation" ],
108
131
Root => Root,
109
132
Error => Error,
@@ -123,7 +146,7 @@ package body LSP.Alire is
123
146
begin
124
147
Project.Clear;
125
148
126
- Start_Alire
149
+ Start_Alire_Sync
127
150
(Options => [" --non-interactive" , " show" ],
128
151
Root => Root,
129
152
Error => Error,
@@ -201,7 +224,7 @@ package body LSP.Alire is
201
224
Lines : VSS.String_Vectors.Virtual_String_Vector;
202
225
begin
203
226
204
- Start_Alire ([" --non-interactive" , " printenv" ], Root, Error, Lines);
227
+ Start_Alire_Sync ([" --non-interactive" , " printenv" ], Root, Error, Lines);
205
228
206
229
if not Error.Is_Empty then
207
230
return ;
@@ -224,11 +247,73 @@ package body LSP.Alire is
224
247
end loop ;
225
248
end Setup_Alire_Env ;
226
249
227
- -- ---------------
228
- -- Start_Alire --
229
- -- ---------------
250
+ -- --------------------
251
+ -- Start_Alire_Sync --
252
+ -- --------------------
230
253
231
- procedure Start_Alire
254
+ procedure Start_Alire_Sync
255
+ (Options : VSS.String_Vectors.Virtual_String_Vector;
256
+ Root : String;
257
+ Error : out VSS.Strings.Virtual_String;
258
+ Lines : out VSS.String_Vectors.Virtual_String_Vector)
259
+ is
260
+ use VSS.Strings;
261
+ use VSS.Strings.Conversions;
262
+
263
+ Lock_File : constant GNAT.Lock_Files.Path_Name :=
264
+ GNATCOLL.VFS.Get_Current_Dir.Create_From_Dir (" .als-alire" )
265
+ .Display_Full_Name;
266
+ Lock_File_VS : constant Virtual_String := To_Virtual_String (Lock_File);
267
+ begin
268
+
269
+ begin
270
+ Trace.Trace_Text (" Acquiring Alire lock file: " & Lock_File_VS);
271
+ GNAT.Lock_Files.Lock_File (Lock_File_Name => Lock_File, Wait => 0.2 );
272
+ exception
273
+ when E : GNAT.Lock_Files.Lock_Error =>
274
+ Trace.Trace_Exception (E);
275
+ Error :=
276
+ " Could not acquire Alire lock file. Try deleting the lock file manually: " ;
277
+ Error.Append (Lock_File_VS);
278
+ return ;
279
+ end ;
280
+
281
+ begin
282
+ begin
283
+ Start_Alire_Unsynced
284
+ (Options => Options,
285
+ Root => Root,
286
+ Error => Error,
287
+ Lines => Lines);
288
+ exception
289
+ when E : others =>
290
+ Trace.Trace_Exception (E);
291
+ Error := " Error running Alire: " ;
292
+ Error.Append
293
+ (To_Virtual_String
294
+ (Ada.Exceptions.Exception_Information (E)));
295
+ Trace.Trace_Text (" Releasing Alire lock file: " & Lock_File_VS);
296
+ GNAT.Lock_Files.Unlock_File (Lock_File);
297
+ return ;
298
+ end ;
299
+
300
+ Trace.Trace_Text (" Releasing Alire lock file: " & Lock_File_VS);
301
+ GNAT.Lock_Files.Unlock_File (Lock_File);
302
+ exception
303
+ when E : others =>
304
+ Trace.Trace_Exception (E);
305
+ Error.Append
306
+ (VSS.Characters.Latin.Line_Feed
307
+ & " Could not release Alire lock file. Try deleting the lock files manually: " );
308
+ Error.Append
309
+ (Lock_File_VS
310
+ & VSS.Characters.Latin.Line_Feed
311
+ & To_Virtual_String (Ada.Exceptions.Exception_Information (E)));
312
+ return ;
313
+ end ;
314
+ end Start_Alire_Sync ;
315
+
316
+ procedure Start_Alire_Unsynced
232
317
(Options : VSS.String_Vectors.Virtual_String_Vector;
233
318
Root : String;
234
319
Error : out VSS.Strings.Virtual_String;
@@ -241,14 +326,13 @@ package body LSP.Alire is
241
326
use VSS.Strings.Formatters.Strings;
242
327
use VSS.Strings.Conversions;
243
328
244
- Item : aliased Process_Listener;
245
- Process : Spawn.Processes.Process renames Item.Process;
329
+ Item : aliased Process_Listener;
330
+ Process : Spawn.Processes.Process renames Item.Process;
246
331
Full_Options : VSS.String_Vectors.Virtual_String_Vector := Options;
247
- Sp_Options : Spawn.String_Vectors.UTF_8_String_Vector;
248
- Decoder : VSS.Strings.Converters.Decoders.Virtual_String_Decoder;
249
- Text : VSS.Strings.Virtual_String;
332
+ Sp_Options : Spawn.String_Vectors.UTF_8_String_Vector;
333
+ Decoder : VSS.Strings.Converters.Decoders.Virtual_String_Decoder;
334
+ Text : VSS.Strings.Virtual_String;
250
335
begin
251
-
252
336
declare
253
337
use type GNAT.OS_Lib.String_Access;
254
338
ALR : GNAT.OS_Lib.String_Access :=
@@ -358,7 +442,7 @@ package body LSP.Alire is
358
442
end if ;
359
443
end if ;
360
444
361
- end Start_Alire ;
445
+ end Start_Alire_Unsynced ;
362
446
363
447
-- ----------------------------
364
448
-- Standard_Error_Available --
@@ -412,7 +496,8 @@ package body LSP.Alire is
412
496
(Client : LSP.Ada_Client_Capabilities.Client_Capability) return Boolean
413
497
is
414
498
Alire_TOML : constant GNATCOLL.VFS.Virtual_File :=
415
- (if Client.Root.Is_Empty then GNATCOLL.VFS.No_File
499
+ (if Client.Root.Is_Empty
500
+ then GNATCOLL.VFS.No_File
416
501
else Client.Root_Directory.Create_From_Dir (" alire.toml" ));
417
502
begin
418
503
return Alire_TOML.Is_Regular_File;
0 commit comments