@@ -228,26 +228,20 @@ package body GNATCOLL.OS.Process is
228228 Status : out Integer)
229229 return Ada.Strings.Unbounded.Unbounded_String
230230 is
231- use type FS.File_Descriptor;
232231 use Ada.Strings.Unbounded;
233232
234233 Pipe_Read, Pipe_Write : OS.FS.File_Descriptor;
235234 Output : Unbounded_String;
236- Real_Stderr_Fd : OS.FS.File_Descriptor := Stderr;
237235 Buffer : String (1 .. 4096 );
238236 Pid : Process_Handle;
239237 N : Integer;
240238 begin
241239 -- Allocate a PIPE to retrieve the output
242240 FS.Open_Pipe (Pipe_Read, Pipe_Write);
243241
244- if Stderr = FS.To_Stdout then
245- Real_Stderr_Fd := Pipe_Write;
246- end if ;
247-
248242 -- Start the process.
249243 Pid := Start
250- (Args, Env, Cwd, Stdin, Pipe_Write, Real_Stderr_Fd , Priority);
244+ (Args, Env, Cwd, Stdin, Pipe_Write, Stderr , Priority);
251245
252246 -- Be sure to close Pipe_Write otherwise following reads on Pipe_Read
253247 -- will block even if the child process ends.
@@ -461,24 +455,75 @@ package body GNATCOLL.OS.Process is
461455 Priority : Priority_Class := INHERIT)
462456 return Process_Handle
463457 is
464- Result : Process_Handle;
458+ Result : Process_Handle;
459+
460+ -- By default final file descriptors are the one passed by the user
461+ Real_Stdin : OS.FS.File_Descriptor := Stdin;
462+ Real_Stdout : OS.FS.File_Descriptor := Stdout;
463+ Real_Stderr : OS.FS.File_Descriptor := Stderr;
464+ Close_Stdin : Boolean := False;
465+ Close_Stdout : Boolean := False;
466+ Close_Stderr : Boolean := False;
467+
468+ use type OS.FS.File_Descriptor;
465469 begin
466470 GNAT.Task_Lock.Lock;
467471
468- FS.Set_Close_On_Exec (Stdin, False);
469- FS.Set_Close_On_Exec (Stdout, False);
470- FS.Set_Close_On_Exec (Stderr, False);
472+ -- Handle special cases for file descriptors
473+ -- First ensure all file descriptors are valid
474+ if Stdout = OS.FS.Invalid_FD then
475+ raise OS_Error with " invalid fd for process stdout" ;
476+ elsif Stdout = OS.FS.Null_FD then
477+ Real_Stdout := OS.FS.Open (OS.FS.Null_File, OS.FS.Write_Mode);
478+ Close_Stdout := True;
479+ elsif Stdout = OS.FS.To_Stdout then
480+ raise OS_Error with " cannot redirect stdout to stdout" ;
481+ end if ;
482+
483+ if Stdin = OS.FS.Invalid_FD then
484+ raise OS_Error with " invalid fd for process stdin" ;
485+ elsif Stdin = OS.FS.Null_FD then
486+ Real_Stdin := OS.FS.Open (OS.FS.Null_File, OS.FS.Read_Mode);
487+ Close_Stdin := True;
488+ elsif Stdin = OS.FS.To_Stdout then
489+ raise OS_Error with " cannot redirect stdin to stdout" ;
490+ end if ;
491+
492+ if Stderr = OS.FS.Invalid_FD then
493+ raise OS_Error with " invalid fd for process stderr" ;
494+ elsif Stderr = OS.FS.Null_FD then
495+ Real_Stderr := OS.FS.Open (OS.FS.Null_File, OS.FS.Write_Mode);
496+ Close_Stderr := True;
497+ elsif Stderr = OS.FS.To_Stdout then
498+ Real_Stderr := Real_Stdout;
499+ end if ;
500+
501+ FS.Set_Close_On_Exec (Real_Stdin, False);
502+ FS.Set_Close_On_Exec (Real_Stdout, False);
503+ FS.Set_Close_On_Exec (Real_Stderr, False);
471504
472505 Result := Internal_Spawn
473506 (Args,
474507 Cwd,
475508 Env,
476- Stdin, Stdout, Stderr ,
509+ Real_Stdin, Real_Stdout, Real_Stderr ,
477510 Priority);
478511
479- FS.Set_Close_On_Exec (Stdin, True);
480- FS.Set_Close_On_Exec (Stdout, True);
481- FS.Set_Close_On_Exec (Stderr, True);
512+ FS.Set_Close_On_Exec (Real_Stdin, True);
513+ FS.Set_Close_On_Exec (Real_Stdout, True);
514+ FS.Set_Close_On_Exec (Real_Stderr, True);
515+
516+ if Close_Stdout then
517+ OS.FS.Close (Real_Stdout);
518+ end if ;
519+
520+ if Close_Stderr then
521+ OS.FS.Close (Real_Stderr);
522+ end if ;
523+
524+ if Close_Stdin then
525+ OS.FS.Close (Real_Stdin);
526+ end if ;
482527
483528 GNAT.Task_Lock.Unlock;
484529 return Result;
0 commit comments