This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Ada] fix handling of fds in gnat.expect


Tested under i686-linux, commited on mainline.

When spawning a process, GNAT.Expect creates pipes to exchange stdin,
stdout and stderr data between the caller (parent) process and the
created child process. However, it does not close in the child the
descriptors used by the parent. Specifically, the write end of the pipe
whose read end is the child's stdin is not closed. This means that the
child inherits this open fd, and thus even if the parent subsequently
closes its copy of that fd, the pipe remains open, and the child never
sees EOF on its standard input. This change addresses the problem
by marking the descriptors as Close-on-Exec. Implementation note:
currently Set_Close_On_Exec is a nop under Windows, but this is not
a problem as descriptors are not inherited by default on this platform.
Test case: father.adb. Compile and run, output must be:
  Got ping
  Child died
(before fix, test case dies with Program_Error after a 5 second delay).
--
with GNAT.Expect; use GNAT.Expect;
with GNAT.OS_Lib; use GNAT.OS_Lib;
with Ada.Text_IO; use Ada.Text_IO;
procedure Father is
   Proc : Process_Descriptor; A : Argument_List (2 .. 1); Result : Expect_Match;
begin
   Non_Blocking_Spawn (Proc, "/bin/cat", A);
   Send (Proc, "ping");
   Close (Get_Input_Fd (Proc));
   loop
      begin
         Expect (Proc, Result, ".+", 1_000);
         if Result = Expect_Timeout then raise Program_Error; end if;
         Put_Line ("Got " & Expect_Out (Proc));
      exception
         when Process_Died => Put_Line ("Child died"); exit;
      end;
   end loop;
end Father;

Plus some VMS clean ups:

Execv argv on VMS requires a 32 bit pointer regardless for default pointer size.
This change enforces that requirement by reallocating argv when necessary.

Char* has a different size on AVMS vs. IVMS,
so __char_ptr32 must be used for the adr field for consistency.

2005-02-09  Doug Rupp  <rupp@adacore.com>
	    Thomas Quinot  <quinot@adacore.com>

	* adaint.c, adaint.h
	[VMS] (to_ptr32): New function.
	(MAYBE_TO_PTR32): New macro.
	(__gnat_portable_spawn,__gnat_portable_no_block_spawn): Adjust argv
	for pointer size.
	[VMS] (descriptor_s, ile_s): Use __char_ptr32 for adr field.
	[VMS] (#define fork()): Remove since unneccessary.
	(__gnat_set_close_on_exec): New routine to support
	GNAT.OS_Lib.Set_Close_On_Exec.

	* g-expect.adb (Set_Up_Communications): Mark the pipe descriptors for
	the parent side as close-on-exec so that they are not inherited by the
	child.

	* g-os_lib.ads, g-os_lib.adb (Set_Close_On_Exec): New subprogram to
	set or clear the FD_CLOEXEC flag on a file descriptor.

Attachment: difs.6
Description: Text document


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]