Skip to content

Commit c6c4bf1

Browse files
committed
Merge branch 'topic/error_no_callbacks' into 'master'
Don't emit Error_Occured on IO errors See merge request eng/ide/spawn!46
2 parents 5e06030 + bf3c793 commit c6c4bf1

28 files changed

+707
-345
lines changed

Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ endif
1919

2020
all:
2121
gprbuild $(GPRBUILD_FLAGS) -P gnat/spawn.gpr
22-
gprbuild $(GPRBUILD_FLAGS) -P gnat/spawn_tests.gpr
22+
gprbuild $(GPRBUILD_FLAGS) -P gnat/spawn_tests.gpr -XSPAWN_LIBRARY_TYPE=static
23+
2324
check:
2425
export LD_LIBRARY_PATH=.libs/spawn/relocatable; \
2526
for TEST in ${SPAWN_TESTS}; do \

gnat/spawn.gpr

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
--
2-
-- Copyright (C) 2018-2022, AdaCore
2+
-- Copyright (C) 2018-2023, AdaCore
33
--
44
-- SPDX-License-Identifier: Apache-2.0
55
--
@@ -10,7 +10,8 @@ library project Spawn is
1010
OS_API : OS_API_Kind := external ("OS", "unix");
1111

1212
type Library_Kind is ("static", "static-pic", "relocatable");
13-
Library_Type : Library_Kind := external ("LIBRARY_TYPE", "static");
13+
Library_Type : Library_Kind :=
14+
external ("SPAWN_LIBRARY_TYPE", external ("LIBRARY_TYPE", "static"));
1415

1516
type Spawn_Build_Kind is ("dev", "prod", "coverage", "AddressSanitizer");
1617
Build_Mode : Spawn_Build_Kind :=
@@ -40,6 +41,7 @@ library project Spawn is
4041
for Excluded_Source_Files use Common_Excluded &
4142
("pipe2.c",
4243
"spawn-windows_api.ads",
44+
"spawn-windows_api.adb",
4345
"spawn-internal-windows.ads",
4446
"spawn-internal-windows.adb");
4547

gnat/spawn_glib.gpr

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
--
2-
-- Copyright (C) 2018-2022, AdaCore
2+
-- Copyright (C) 2018-2023, AdaCore
33
--
44
-- SPDX-License-Identifier: Apache-2.0
55
--
@@ -12,7 +12,8 @@ library project Spawn_Glib is
1212
OS_API : OS_API_Kind := external ("OS", "unix");
1313

1414
type Library_Kind is ("static", "static-pic", "relocatable");
15-
Library_Type : Library_Kind := external ("LIBRARY_TYPE", "static");
15+
Library_Type : Library_Kind :=
16+
external ("SPAWN_GLIB_LIBRARY_TYPE", external ("LIBRARY_TYPE", "static"));
1617

1718
type Spawn_Glib_Build_Kind is ("dev", "prod", "coverage");
1819
Build_Mode : Spawn_Glib_Build_Kind :=
@@ -48,6 +49,7 @@ library project Spawn_Glib is
4849
when "unix" | "osx" =>
4950
for Excluded_Source_Files use Common_Excluded &
5051
("spawn-windows_api.ads",
52+
"spawn-windows_api.adb",
5153
"spawn-internal-windows.ads",
5254
"spawn-internal-windows.adb");
5355

source/spawn/spawn-channels__glib_posix.adb

Lines changed: 93 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
--
2-
-- Copyright (C) 2018-2022, AdaCore
2+
-- Copyright (C) 2018-2023, AdaCore
33
--
44
-- SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
55
--
@@ -76,7 +76,28 @@ package body Spawn.Channels is
7676
with Convention => C;
7777
-- Common code to start (continue) watching of the IO channel.
7878

79-
procedure On_Close_Channels (Self : Channels);
79+
procedure Channel_Error (Self : Channels);
80+
-- Executed on IO channel failure to report postponed Finished signal.
81+
82+
-------------------
83+
-- Channel_Error --
84+
-------------------
85+
86+
procedure Channel_Error (Self : Channels) is
87+
begin
88+
if Self.Process.Pending_Finish then
89+
-- Check whether all IO operations are done, then emit Finished
90+
-- callback.
91+
92+
if not Is_Active (Self) then
93+
Self.Process.Pending_Finish := False;
94+
Self.Process.Status := Not_Running;
95+
96+
Self.Process.Emit_Finished
97+
(Self.Process.Exit_Status, Self.Process.Exit_Code);
98+
end if;
99+
end if;
100+
end Channel_Error;
80101

81102
-----------------------------
82103
-- Close_Child_Descriptors --
@@ -113,28 +134,12 @@ package body Spawn.Channels is
113134

114135
function Is_Active (Self : Channels) return Boolean is
115136
begin
116-
return Self.Stdout_Event /= Glib.Main.No_Source_Id
117-
or Self.Stderr_Event /= Glib.Main.No_Source_Id;
137+
return
138+
Self.Stdin_Event /= Glib.Main.No_Source_Id
139+
or Self.Stdout_Event /= Glib.Main.No_Source_Id
140+
or Self.Stderr_Event /= Glib.Main.No_Source_Id;
118141
end Is_Active;
119142

120-
-----------------------
121-
-- On_Close_Channels --
122-
-----------------------
123-
124-
procedure On_Close_Channels (Self : Channels) is
125-
begin
126-
if Self.Process.Pending_Finish then
127-
Self.Process.Pending_Finish := False;
128-
Self.Process.Status := Not_Running;
129-
130-
Self.Process.Emit_Finished
131-
(Self.Process.Exit_Status, Self.Process.Exit_Code);
132-
end if;
133-
exception
134-
when others =>
135-
null;
136-
end On_Close_Channels;
137-
138143
---------------------
139144
-- On_Stderr_Event --
140145
---------------------
@@ -149,23 +154,26 @@ package body Spawn.Channels is
149154
Self : Channels renames data.Self.Channels;
150155

151156
begin
152-
if (condition and Glib.IOChannel.G_Io_In) /= 0 then
153-
Self.Stderr_Lock := @ - 1;
157+
Self.Stderr_Lock := @ - 1;
154158

159+
if (condition and Glib.IOChannel.G_Io_In) /= 0 then
155160
Self.Process.Emit_Stderr_Available;
156161

157-
if Self.Stderr_Lock = 0 then
158-
Self.Stderr_Event := Glib.Main.No_Source_Id;
159-
end if;
162+
elsif (condition and Glib.IOChannel.G_Io_Hup) /= 0
163+
or (condition and Glib.IOChannel.G_Io_Err) /= 0
164+
then
165+
Self.Process.Emit_Standard_Error_Stream_Error
166+
("GIOChannel IO error");
160167
end if;
161168

162-
if (condition and Glib.IOChannel.G_Io_Hup) /= 0 then
163-
Self.Stderr_Lock := 0;
169+
if Self.Stderr_Lock = 0 then
164170
Self.Stderr_Event := Glib.Main.No_Source_Id;
171+
end if;
165172

166-
if Self.Stdout_Event = Glib.Main.No_Source_Id then
167-
On_Close_Channels (Self);
168-
end if;
173+
if (condition and Glib.IOChannel.G_Io_Hup) /= 0
174+
or (condition and Glib.IOChannel.G_Io_Err) /= 0
175+
then
176+
Channel_Error (Self);
169177
end if;
170178

171179
return Self.Stderr_Lock;
@@ -181,19 +189,32 @@ package body Spawn.Channels is
181189
data : access Internal.Process_Reference) return Glib.Gboolean
182190
is
183191
pragma Unreferenced (source);
184-
pragma Unreferenced (condition);
185192

186193
Self : Channels renames data.Self.Channels;
187194

188195
begin
189196
Self.Stdin_Lock := @ - 1;
190197

191-
Self.Process.Emit_Stdin_Available;
198+
if (condition and Glib.IOChannel.G_Io_Out) /= 0 then
199+
Self.Process.Emit_Stdin_Available;
200+
201+
elsif (condition and Glib.IOChannel.G_Io_Hup) /= 0
202+
or (condition and Glib.IOChannel.G_Io_Err) /= 0
203+
then
204+
Self.Process.Emit_Standard_Error_Stream_Error
205+
("GIOChannel IO error");
206+
end if;
192207

193208
if Self.Stdin_Lock = 0 then
194209
Self.Stdin_Event := Glib.Main.No_Source_Id;
195210
end if;
196211

212+
if (condition and Glib.IOChannel.G_Io_Hup) /= 0
213+
or (condition and Glib.IOChannel.G_Io_Err) /= 0
214+
then
215+
Channel_Error (Self);
216+
end if;
217+
197218
return Self.Stdin_Lock;
198219
end On_Stdin_Event;
199220

@@ -211,23 +232,26 @@ package body Spawn.Channels is
211232
Self : Channels renames data.Self.Channels;
212233

213234
begin
214-
if (condition and Glib.IOChannel.G_Io_In) /= 0 then
215-
Self.Stdout_Lock := @ - 1;
235+
Self.Stdout_Lock := @ - 1;
216236

237+
if (condition and Glib.IOChannel.G_Io_In) /= 0 then
217238
Self.Process.Emit_Stdout_Available;
218239

219-
if Self.Stdout_Lock = 0 then
220-
Self.Stdout_Event := Glib.Main.No_Source_Id;
221-
end if;
240+
elsif (condition and Glib.IOChannel.G_Io_Hup) /= 0
241+
or (condition and Glib.IOChannel.G_Io_Err) /= 0
242+
then
243+
Self.Process.Emit_Standard_Output_Stream_Error
244+
("GIOChannel IO error");
222245
end if;
223246

224-
if (condition and Glib.IOChannel.G_Io_Hup) /= 0 then
225-
Self.Stdout_Lock := 0;
247+
if Self.Stdout_Lock = 0 then
226248
Self.Stdout_Event := Glib.Main.No_Source_Id;
249+
end if;
227250

228-
if Self.Stderr_Event = Glib.Main.No_Source_Id then
229-
On_Close_Channels (Self);
230-
end if;
251+
if (condition and Glib.IOChannel.G_Io_Hup) /= 0
252+
or (condition and Glib.IOChannel.G_Io_Err) /= 0
253+
then
254+
Channel_Error (Self);
231255
end if;
232256

233257
return Self.Stdout_Lock;
@@ -247,9 +271,10 @@ package body Spawn.Channels is
247271
-----------------
248272

249273
procedure Read_Stderr
250-
(Self : in out Channels;
251-
Data : out Ada.Streams.Stream_Element_Array;
252-
Last : out Ada.Streams.Stream_Element_Offset)
274+
(Self : in out Channels;
275+
Data : out Ada.Streams.Stream_Element_Array;
276+
Last : out Ada.Streams.Stream_Element_Offset;
277+
Success : in out Boolean)
253278
is
254279
use type Glib.Gsize;
255280

@@ -272,6 +297,7 @@ package body Spawn.Channels is
272297
Buf => Data,
273298
Bytes_Read => Count'Access,
274299
Error => Error'Access);
300+
275301
case Status is
276302
when Glib.IOChannel.G_Io_Status_Eof =>
277303
-- Reading is completed, so no watching is required
@@ -292,8 +318,7 @@ package body Spawn.Channels is
292318
Start_Stderr_Watch (Self);
293319

294320
when Glib.IOChannel.G_Io_Status_Error =>
295-
Self.Process.Emit_Error_Occurred
296-
(Integer (Glib.Error.Get_Code (Error)));
321+
Success := False;
297322
end case;
298323
end Read_Stderr;
299324

@@ -302,9 +327,10 @@ package body Spawn.Channels is
302327
-----------------
303328

304329
procedure Read_Stdout
305-
(Self : in out Channels;
306-
Data : out Ada.Streams.Stream_Element_Array;
307-
Last : out Ada.Streams.Stream_Element_Offset)
330+
(Self : in out Channels;
331+
Data : out Ada.Streams.Stream_Element_Array;
332+
Last : out Ada.Streams.Stream_Element_Offset;
333+
Success : in out Boolean)
308334
is
309335
use type Glib.Gsize;
310336

@@ -346,8 +372,7 @@ package body Spawn.Channels is
346372
Start_Stdout_Watch (Self);
347373

348374
when Glib.IOChannel.G_Io_Status_Error =>
349-
Self.Process.Emit_Error_Occurred
350-
(Integer (Glib.Error.Get_Code (Error)));
375+
Success := False;
351376
end case;
352377
end Read_Stdout;
353378

@@ -756,7 +781,9 @@ package body Spawn.Channels is
756781
(Self.Stderr_Parent,
757782
Self.Stderr_Event,
758783
Self.Stderr_Lock,
759-
Glib.IOChannel.G_Io_In + Glib.IOChannel.G_Io_Hup,
784+
Glib.IOChannel.G_Io_In
785+
+ Glib.IOChannel.G_Io_Hup
786+
+ Glib.IOChannel.G_Io_Err,
760787
On_Stderr_Event'Access,
761788
Self.Process.Reference'Unchecked_Access);
762789
end if;
@@ -772,7 +799,9 @@ package body Spawn.Channels is
772799
(Self.Stdin_Parent,
773800
Self.Stdin_Event,
774801
Self.Stdin_Lock,
775-
Glib.IOChannel.G_Io_Out,
802+
Glib.IOChannel.G_Io_Out
803+
+ Glib.IOChannel.G_Io_Hup
804+
+ Glib.IOChannel.G_Io_Err,
776805
On_Stdin_Event'Access,
777806
Self.Process.Reference'Unchecked_Access);
778807
end Start_Stdin_Watch;
@@ -787,7 +816,9 @@ package body Spawn.Channels is
787816
(Self.Stdout_Parent,
788817
Self.Stdout_Event,
789818
Self.Stdout_Lock,
790-
Glib.IOChannel.G_Io_In + Glib.IOChannel.G_Io_Hup,
819+
Glib.IOChannel.G_Io_In
820+
+ Glib.IOChannel.G_Io_Hup
821+
+ Glib.IOChannel.G_Io_Err,
791822
On_Stdout_Event'Access,
792823
Self.Process.Reference'Unchecked_Access);
793824
end Start_Stdout_Watch;
@@ -835,9 +866,10 @@ package body Spawn.Channels is
835866
-----------------
836867

837868
procedure Write_Stdin
838-
(Self : in out Channels;
839-
Data : Ada.Streams.Stream_Element_Array;
840-
Last : out Ada.Streams.Stream_Element_Offset)
869+
(Self : in out Channels;
870+
Data : Ada.Streams.Stream_Element_Array;
871+
Last : out Ada.Streams.Stream_Element_Offset;
872+
Success : in out Boolean)
841873
is
842874
Error : aliased Glib.Error.GError;
843875
Count : aliased Glib.Gsize;
@@ -871,8 +903,7 @@ package body Spawn.Channels is
871903
Start_Stdin_Watch (Self);
872904

873905
when Glib.IOChannel.G_Io_Status_Error =>
874-
Self.Process.Emit_Error_Occurred
875-
(Integer (Glib.Error.Get_Code (Error)));
906+
Success := False;
876907

877908
when others =>
878909
raise Program_Error;

0 commit comments

Comments
 (0)