diff gcc/ada/libgnat/g-expect.adb @ 145:1830386684a0

gcc-9.2.0
author anatofuz
date Thu, 13 Feb 2020 11:34:05 +0900
parents 84e7813d76e9
children
line wrap: on
line diff
--- a/gcc/ada/libgnat/g-expect.adb	Thu Oct 25 07:37:49 2018 +0900
+++ b/gcc/ada/libgnat/g-expect.adb	Thu Feb 13 11:34:05 2020 +0900
@@ -6,7 +6,7 @@
 --                                                                          --
 --                                 B o d y                                  --
 --                                                                          --
---                     Copyright (C) 2000-2018, AdaCore                     --
+--                     Copyright (C) 2000-2019, AdaCore                     --
 --                                                                          --
 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
 -- terms of the  GNU General Public License as published  by the Free Soft- --
@@ -222,15 +222,17 @@
       Next_Filter    : Filter_List;
 
    begin
-      if Descriptor.Input_Fd /= Invalid_FD then
-         Close (Descriptor.Input_Fd);
-      end if;
+      Close_Input (Descriptor);
 
-      if Descriptor.Error_Fd /= Descriptor.Output_Fd then
+      if Descriptor.Error_Fd /= Descriptor.Output_Fd
+        and then Descriptor.Error_Fd /= Invalid_FD
+      then
          Close (Descriptor.Error_Fd);
       end if;
 
-      Close (Descriptor.Output_Fd);
+      if Descriptor.Output_Fd /= Invalid_FD then
+         Close (Descriptor.Output_Fd);
+      end if;
 
       --  ??? Should have timeouts for different signals
 
@@ -267,6 +269,27 @@
       Close (Descriptor, Status);
    end Close;
 
+   -----------------
+   -- Close_Input --
+   -----------------
+
+   procedure Close_Input (Pid : in out Process_Descriptor) is
+   begin
+      if Pid.Input_Fd /= Invalid_FD then
+         Close (Pid.Input_Fd);
+      end if;
+
+      if Pid.Output_Fd = Pid.Input_Fd then
+         Pid.Output_Fd := Invalid_FD;
+      end if;
+
+      if Pid.Error_Fd = Pid.Input_Fd then
+         Pid.Error_Fd := Invalid_FD;
+      end if;
+
+      Pid.Input_Fd := Invalid_FD;
+   end Close_Input;
+
    ------------
    -- Expect --
    ------------
@@ -630,7 +653,9 @@
 
    begin
       for J in Descriptors'Range loop
-         if Descriptors (J) /= null then
+         if Descriptors (J) /= null
+           and then Descriptors (J).Output_Fd /= Invalid_FD
+         then
             Fds (Fds'First + Fds_Count) := Descriptors (J).Output_Fd;
             Fds_To_Descriptor (Fds'First + Fds_Count) := J;
             Fds_Count := Fds_Count + 1;
@@ -644,6 +669,14 @@
          end if;
       end loop;
 
+      if Fds_Count = 0 then
+         --  There are no descriptors to monitor, it means that process died.
+
+         Result := Expect_Process_Died;
+
+         return;
+      end if;
+
       declare
          Buffer : aliased String (1 .. Buffer_Size);
          --  Buffer used for input. This is allocated only once, not for
@@ -656,8 +689,17 @@
          --  Loop until we match or we have a timeout
 
          loop
-            Num_Descriptors :=
-              Poll (Fds'Address, Fds_Count, Timeout, D'Access, Is_Set'Address);
+            --  Poll may be interrupted on Linux by a signal and need to be
+            --  repeated. We don't want to check for errno = EINTER, so just
+            --  attempt to call Poll a few times.
+
+            for J in 1 .. 3 loop
+               Num_Descriptors :=
+                 Poll
+                   (Fds'Address, Fds_Count, Timeout, D'Access, Is_Set'Address);
+
+               exit when Num_Descriptors /= -1;
+            end loop;
 
             case Num_Descriptors is
 
@@ -667,8 +709,7 @@
                   Result := Expect_Internal_Error;
 
                   if D /= 0 then
-                     Close (Descriptors (D).Input_Fd);
-                     Descriptors (D).Input_Fd := Invalid_FD;
+                     Close_Input (Descriptors (D).all);
                   end if;
 
                   return;
@@ -692,18 +733,24 @@
                            Buffer_Size := 4096;
                         end if;
 
-                        N := Read (Descriptors (D).Output_Fd, Buffer'Address,
-                                   Buffer_Size);
+                        --  Read may be interrupted on Linux by a signal and
+                        --  need to be repeated. We don't want to check for
+                        --  errno = EINTER, so just attempt to read a few
+                        --  times.
+
+                        for J in 1 .. 3 loop
+                           N := Read (Descriptors (D).Output_Fd,
+                                      Buffer'Address, Buffer_Size);
+
+                           exit when N > 0;
+                        end loop;
 
                         --  Error or End of file
 
                         if N <= 0 then
-                           --  ??? Note that ddd tries again up to three times
-                           --  in that case. See LiterateA.C:174
+                           Close_Input (Descriptors (D).all);
+                           Result := Expect_Process_Died;
 
-                           Close (Descriptors (D).Input_Fd);
-                           Descriptors (D).Input_Fd := Invalid_FD;
-                           Result := Expect_Process_Died;
                            return;
 
                         else
@@ -925,8 +972,7 @@
          Send (Process, Input);
       end if;
 
-      Close (Process.Input_Fd);
-      Process.Input_Fd := Invalid_FD;
+      Close_Input (Process);
 
       declare
          Result : Expect_Match;