1
1
--
2
- -- Copyright (C) 2018-2022 , AdaCore
2
+ -- Copyright (C) 2018-2023 , AdaCore
3
3
--
4
4
-- SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5
5
--
@@ -76,7 +76,28 @@ package body Spawn.Channels is
76
76
with Convention => C;
77
77
-- Common code to start (continue) watching of the IO channel.
78
78
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 ;
80
101
81
102
-- ---------------------------
82
103
-- Close_Child_Descriptors --
@@ -113,28 +134,12 @@ package body Spawn.Channels is
113
134
114
135
function Is_Active (Self : Channels) return Boolean is
115
136
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;
118
141
end Is_Active ;
119
142
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
-
138
143
-- -------------------
139
144
-- On_Stderr_Event --
140
145
-- -------------------
@@ -149,23 +154,26 @@ package body Spawn.Channels is
149
154
Self : Channels renames data.Self.Channels;
150
155
151
156
begin
152
- if (condition and Glib.IOChannel.G_Io_In) /= 0 then
153
- Self.Stderr_Lock := @ - 1 ;
157
+ Self.Stderr_Lock := @ - 1 ;
154
158
159
+ if (condition and Glib.IOChannel.G_Io_In) /= 0 then
155
160
Self.Process.Emit_Stderr_Available;
156
161
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" );
160
167
end if ;
161
168
162
- if (condition and Glib.IOChannel.G_Io_Hup) /= 0 then
163
- Self.Stderr_Lock := 0 ;
169
+ if Self.Stderr_Lock = 0 then
164
170
Self.Stderr_Event := Glib.Main.No_Source_Id;
171
+ end if ;
165
172
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);
169
177
end if ;
170
178
171
179
return Self.Stderr_Lock;
@@ -181,19 +189,32 @@ package body Spawn.Channels is
181
189
data : access Internal.Process_Reference) return Glib.Gboolean
182
190
is
183
191
pragma Unreferenced (source);
184
- pragma Unreferenced (condition);
185
192
186
193
Self : Channels renames data.Self.Channels;
187
194
188
195
begin
189
196
Self.Stdin_Lock := @ - 1 ;
190
197
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 ;
192
207
193
208
if Self.Stdin_Lock = 0 then
194
209
Self.Stdin_Event := Glib.Main.No_Source_Id;
195
210
end if ;
196
211
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
+
197
218
return Self.Stdin_Lock;
198
219
end On_Stdin_Event ;
199
220
@@ -211,23 +232,26 @@ package body Spawn.Channels is
211
232
Self : Channels renames data.Self.Channels;
212
233
213
234
begin
214
- if (condition and Glib.IOChannel.G_Io_In) /= 0 then
215
- Self.Stdout_Lock := @ - 1 ;
235
+ Self.Stdout_Lock := @ - 1 ;
216
236
237
+ if (condition and Glib.IOChannel.G_Io_In) /= 0 then
217
238
Self.Process.Emit_Stdout_Available;
218
239
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" );
222
245
end if ;
223
246
224
- if (condition and Glib.IOChannel.G_Io_Hup) /= 0 then
225
- Self.Stdout_Lock := 0 ;
247
+ if Self.Stdout_Lock = 0 then
226
248
Self.Stdout_Event := Glib.Main.No_Source_Id;
249
+ end if ;
227
250
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);
231
255
end if ;
232
256
233
257
return Self.Stdout_Lock;
@@ -247,9 +271,10 @@ package body Spawn.Channels is
247
271
-- ---------------
248
272
249
273
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)
253
278
is
254
279
use type Glib.Gsize;
255
280
@@ -272,6 +297,7 @@ package body Spawn.Channels is
272
297
Buf => Data,
273
298
Bytes_Read => Count'Access ,
274
299
Error => Error'Access );
300
+
275
301
case Status is
276
302
when Glib.IOChannel.G_Io_Status_Eof =>
277
303
-- Reading is completed, so no watching is required
@@ -292,8 +318,7 @@ package body Spawn.Channels is
292
318
Start_Stderr_Watch (Self);
293
319
294
320
when Glib.IOChannel.G_Io_Status_Error =>
295
- Self.Process.Emit_Error_Occurred
296
- (Integer (Glib.Error.Get_Code (Error)));
321
+ Success := False;
297
322
end case ;
298
323
end Read_Stderr ;
299
324
@@ -302,9 +327,10 @@ package body Spawn.Channels is
302
327
-- ---------------
303
328
304
329
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)
308
334
is
309
335
use type Glib.Gsize;
310
336
@@ -346,8 +372,7 @@ package body Spawn.Channels is
346
372
Start_Stdout_Watch (Self);
347
373
348
374
when Glib.IOChannel.G_Io_Status_Error =>
349
- Self.Process.Emit_Error_Occurred
350
- (Integer (Glib.Error.Get_Code (Error)));
375
+ Success := False;
351
376
end case ;
352
377
end Read_Stdout ;
353
378
@@ -756,7 +781,9 @@ package body Spawn.Channels is
756
781
(Self.Stderr_Parent,
757
782
Self.Stderr_Event,
758
783
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,
760
787
On_Stderr_Event'Access ,
761
788
Self.Process.Reference'Unchecked_Access);
762
789
end if ;
@@ -772,7 +799,9 @@ package body Spawn.Channels is
772
799
(Self.Stdin_Parent,
773
800
Self.Stdin_Event,
774
801
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,
776
805
On_Stdin_Event'Access ,
777
806
Self.Process.Reference'Unchecked_Access);
778
807
end Start_Stdin_Watch ;
@@ -787,7 +816,9 @@ package body Spawn.Channels is
787
816
(Self.Stdout_Parent,
788
817
Self.Stdout_Event,
789
818
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,
791
822
On_Stdout_Event'Access ,
792
823
Self.Process.Reference'Unchecked_Access);
793
824
end Start_Stdout_Watch ;
@@ -835,9 +866,10 @@ package body Spawn.Channels is
835
866
-- ---------------
836
867
837
868
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)
841
873
is
842
874
Error : aliased Glib.Error.GError;
843
875
Count : aliased Glib.Gsize;
@@ -871,8 +903,7 @@ package body Spawn.Channels is
871
903
Start_Stdin_Watch (Self);
872
904
873
905
when Glib.IOChannel.G_Io_Status_Error =>
874
- Self.Process.Emit_Error_Occurred
875
- (Integer (Glib.Error.Get_Code (Error)));
906
+ Success := False;
876
907
877
908
when others =>
878
909
raise Program_Error;
0 commit comments