Report async IO errors by Glib implementation.

This commit is contained in:
Vadim Godunko
2023-04-04 11:35:50 +04:00
parent e4a72f6ca7
commit c219cd6f86
2 changed files with 87 additions and 48 deletions

View File

@@ -76,7 +76,28 @@ package body Spawn.Channels is
with Convention => C;
-- Common code to start (continue) watching of the IO channel.
procedure On_Close_Channels (Self : Channels);
procedure Channel_Error (Self : Channels);
-- Executed on IO channel failure to report postponed Finished signal.
-------------------
-- Channel_Error --
-------------------
procedure Channel_Error (Self : Channels) is
begin
if Self.Process.Pending_Finish then
-- Check whether all IO operations are done, then emit Finished
-- callback.
if not Is_Active (Self) then
Self.Process.Pending_Finish := False;
Self.Process.Status := Not_Running;
Self.Process.Emit_Finished
(Self.Process.Exit_Status, Self.Process.Exit_Code);
end if;
end if;
end Channel_Error;
-----------------------------
-- Close_Child_Descriptors --
@@ -113,28 +134,12 @@ package body Spawn.Channels is
function Is_Active (Self : Channels) return Boolean is
begin
return Self.Stdout_Event /= Glib.Main.No_Source_Id
or Self.Stderr_Event /= Glib.Main.No_Source_Id;
return
Self.Stdin_Event /= Glib.Main.No_Source_Id
or Self.Stdout_Event /= Glib.Main.No_Source_Id
or Self.Stderr_Event /= Glib.Main.No_Source_Id;
end Is_Active;
-----------------------
-- On_Close_Channels --
-----------------------
procedure On_Close_Channels (Self : Channels) is
begin
if Self.Process.Pending_Finish then
Self.Process.Pending_Finish := False;
Self.Process.Status := Not_Running;
Self.Process.Emit_Finished
(Self.Process.Exit_Status, Self.Process.Exit_Code);
end if;
exception
when others =>
null;
end On_Close_Channels;
---------------------
-- On_Stderr_Event --
---------------------
@@ -149,26 +154,29 @@ package body Spawn.Channels is
Self : Channels renames data.Self.Channels;
begin
if (condition and Glib.IOChannel.G_Io_In) /= 0 then
Self.Stderr_Lock := @ - 1;
Self.Stderr_Lock := @ - 1;
if (condition and Glib.IOChannel.G_Io_In) /= 0 then
Self.Process.Emit_Stderr_Available;
if Self.Stderr_Lock = 0 then
Self.Stderr_Event := Glib.Main.No_Source_Id;
end if;
elsif (condition and Glib.IOChannel.G_Io_Hup) /= 0
or (condition and Glib.IOChannel.G_Io_Err) /= 0
then
Self.Process.Emit_Standard_Error_Stream_Error
("GIOChannel IO error");
end if;
if (condition and Glib.IOChannel.G_Io_Hup) /= 0 then
Self.Stderr_Lock := 0;
if Self.Stderr_Lock = 0 then
Self.Stderr_Event := Glib.Main.No_Source_Id;
if Self.Stdout_Event = Glib.Main.No_Source_Id then
On_Close_Channels (Self);
end if;
end if;
return Self.Stderr_Lock;
if (condition and Glib.IOChannel.G_Io_Hup) /= 0
or (condition and Glib.IOChannel.G_Io_Err) /= 0
then
Channel_Error (Self);
end if;
return Self.Stdout_Lock;
end On_Stderr_Event;
--------------------
@@ -181,19 +189,32 @@ package body Spawn.Channels is
data : access Internal.Process_Reference) return Glib.Gboolean
is
pragma Unreferenced (source);
pragma Unreferenced (condition);
Self : Channels renames data.Self.Channels;
begin
Self.Stdin_Lock := @ - 1;
Self.Process.Emit_Stdin_Available;
if (condition and Glib.IOChannel.G_Io_Out) /= 0 then
Self.Process.Emit_Stdin_Available;
elsif (condition and Glib.IOChannel.G_Io_Hup) /= 0
or (condition and Glib.IOChannel.G_Io_Err) /= 0
then
Self.Process.Emit_Standard_Error_Stream_Error
("GIOChannel IO error");
end if;
if Self.Stdin_Lock = 0 then
Self.Stdin_Event := Glib.Main.No_Source_Id;
end if;
if (condition and Glib.IOChannel.G_Io_Hup) /= 0
or (condition and Glib.IOChannel.G_Io_Err) /= 0
then
Channel_Error (Self);
end if;
return Self.Stdin_Lock;
end On_Stdin_Event;
@@ -211,23 +232,26 @@ package body Spawn.Channels is
Self : Channels renames data.Self.Channels;
begin
if (condition and Glib.IOChannel.G_Io_In) /= 0 then
Self.Stdout_Lock := @ - 1;
Self.Stdout_Lock := @ - 1;
if (condition and Glib.IOChannel.G_Io_In) /= 0 then
Self.Process.Emit_Stdout_Available;
if Self.Stdout_Lock = 0 then
Self.Stdout_Event := Glib.Main.No_Source_Id;
end if;
elsif (condition and Glib.IOChannel.G_Io_Hup) /= 0
or (condition and Glib.IOChannel.G_Io_Err) /= 0
then
Self.Process.Emit_Standard_Output_Stream_Error
("GIOChannel IO error");
end if;
if (condition and Glib.IOChannel.G_Io_Hup) /= 0 then
Self.Stdout_Lock := 0;
if Self.Stdout_Lock = 0 then
Self.Stdout_Event := Glib.Main.No_Source_Id;
end if;
if Self.Stderr_Event = Glib.Main.No_Source_Id then
On_Close_Channels (Self);
end if;
if (condition and Glib.IOChannel.G_Io_Hup) /= 0
or (condition and Glib.IOChannel.G_Io_Err) /= 0
then
Channel_Error (Self);
end if;
return Self.Stdout_Lock;
@@ -757,7 +781,9 @@ package body Spawn.Channels is
(Self.Stderr_Parent,
Self.Stderr_Event,
Self.Stderr_Lock,
Glib.IOChannel.G_Io_In + Glib.IOChannel.G_Io_Hup,
Glib.IOChannel.G_Io_In
+ Glib.IOChannel.G_Io_Hup
+ Glib.IOChannel.G_Io_Err,
On_Stderr_Event'Access,
Self.Process.Reference'Unchecked_Access);
end if;
@@ -773,7 +799,9 @@ package body Spawn.Channels is
(Self.Stdin_Parent,
Self.Stdin_Event,
Self.Stdin_Lock,
Glib.IOChannel.G_Io_Out,
Glib.IOChannel.G_Io_Out
+ Glib.IOChannel.G_Io_Hup
+ Glib.IOChannel.G_Io_Err,
On_Stdin_Event'Access,
Self.Process.Reference'Unchecked_Access);
end Start_Stdin_Watch;
@@ -788,7 +816,9 @@ package body Spawn.Channels is
(Self.Stdout_Parent,
Self.Stdout_Event,
Self.Stdout_Lock,
Glib.IOChannel.G_Io_In + Glib.IOChannel.G_Io_Hup,
Glib.IOChannel.G_Io_In
+ Glib.IOChannel.G_Io_Hup
+ Glib.IOChannel.G_Io_Err,
On_Stdout_Event'Access,
Self.Process.Reference'Unchecked_Access);
end Start_Stdout_Watch;

View File

@@ -71,16 +71,25 @@ private
Stdin_Child : Glib.Gint := -1;
Stdin_Event : Glib.Main.G_Source_Id := Glib.Main.No_Source_Id;
Stdin_Lock : Glib.Gboolean := 0;
-- Lock of the Stdin_Event field. Lock is managed as counter
-- to prevent reset of the Stdin_Event field by the nested IO
-- operation on the channel.
Stdout_Parent : Glib.IOChannel.Giochannel := null;
Stdout_Child : Glib.Gint := -1;
Stdout_Event : Glib.Main.G_Source_Id := Glib.Main.No_Source_Id;
Stdout_Lock : Glib.Gboolean := 0;
-- Lock of the Stdout_Event field. Lock is managed as counter
-- to prevent reset of the Stdout_Event field by the nested IO
-- operation on the channel.
Stderr_Parent : Glib.IOChannel.Giochannel := null;
Stderr_Child : Glib.Gint := -1;
Stderr_Event : Glib.Main.G_Source_Id := Glib.Main.No_Source_Id;
Stderr_Lock : Glib.Gboolean := 0;
-- Lock of the Stderr_Event field. Lock is managed as counter
-- to prevent reset of the Stderr_Event field by the nested IO
-- operation on the channel.
PTY_Slave : Glib.Gint := -1;
end record;