1515-- of the license. --
1616-- ----------------------------------------------------------------------------
1717
18+ with Ada.Exceptions ;
1819with Ada.Streams ;
20+ with GNAT.Lock_Files ;
1921with GNAT.OS_Lib ;
2022with GNATCOLL.Traces ;
2123with GNATCOLL.VFS ;
@@ -42,7 +44,8 @@ package body LSP.Alire is
4244 GNATCOLL_Tracers.Create (" ALS.ALIRE" , GNATCOLL.Traces.On);
4345
4446 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);
4649
4750 type Process_Listener is limited
4851 new Spawn.Process_Listeners.Process_Listener
@@ -63,11 +66,31 @@ package body LSP.Alire is
6366 overriding
6467 procedure Error_Occurred (Self : in out Process_Listener; Error : Integer);
6568
66- procedure Start_Alire
69+ procedure Start_Alire_Sync
6770 (Options : VSS.String_Vectors.Virtual_String_Vector;
6871 Root : String;
6972 Error : out VSS.Strings.Virtual_String;
7073 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.
7194
7295 Anchored : constant VSS.Regular_Expressions.Match_Options :=
7396 (VSS.Regular_Expressions.Anchored_Match => True);
@@ -103,7 +126,7 @@ package body LSP.Alire is
103126 is
104127 Lines : VSS.String_Vectors.Virtual_String_Vector;
105128 begin
106- Start_Alire
129+ Start_Alire_Sync
107130 (Options => [" --non-interactive" , " build" , " --stop-after=generation" ],
108131 Root => Root,
109132 Error => Error,
@@ -123,7 +146,7 @@ package body LSP.Alire is
123146 begin
124147 Project.Clear;
125148
126- Start_Alire
149+ Start_Alire_Sync
127150 (Options => [" --non-interactive" , " show" ],
128151 Root => Root,
129152 Error => Error,
@@ -201,7 +224,7 @@ package body LSP.Alire is
201224 Lines : VSS.String_Vectors.Virtual_String_Vector;
202225 begin
203226
204- Start_Alire ([" --non-interactive" , " printenv" ], Root, Error, Lines);
227+ Start_Alire_Sync ([" --non-interactive" , " printenv" ], Root, Error, Lines);
205228
206229 if not Error.Is_Empty then
207230 return ;
@@ -224,11 +247,73 @@ package body LSP.Alire is
224247 end loop ;
225248 end Setup_Alire_Env ;
226249
227- -- ---------------
228- -- Start_Alire --
229- -- ---------------
250+ -- --------------------
251+ -- Start_Alire_Sync --
252+ -- --------------------
230253
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
232317 (Options : VSS.String_Vectors.Virtual_String_Vector;
233318 Root : String;
234319 Error : out VSS.Strings.Virtual_String;
@@ -241,14 +326,13 @@ package body LSP.Alire is
241326 use VSS.Strings.Formatters.Strings;
242327 use VSS.Strings.Conversions;
243328
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;
246331 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;
250335 begin
251-
252336 declare
253337 use type GNAT.OS_Lib.String_Access;
254338 ALR : GNAT.OS_Lib.String_Access :=
@@ -358,7 +442,7 @@ package body LSP.Alire is
358442 end if ;
359443 end if ;
360444
361- end Start_Alire ;
445+ end Start_Alire_Unsynced ;
362446
363447 -- ----------------------------
364448 -- Standard_Error_Available --
@@ -412,7 +496,8 @@ package body LSP.Alire is
412496 (Client : LSP.Ada_Client_Capabilities.Client_Capability) return Boolean
413497 is
414498 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
416501 else Client.Root_Directory.Create_From_Dir (" alire.toml" ));
417502 begin
418503 return Alire_TOML.Is_Regular_File;
0 commit comments