|
1 | 1 | ------------------------------------------------------------------------------ |
2 | 2 | -- G N A T C O L L -- |
3 | 3 | -- -- |
4 | | --- Copyright (C) 2021, AdaCore -- |
| 4 | +-- Copyright (C) 2021-2022, AdaCore -- |
5 | 5 | -- -- |
6 | 6 | -- This library is free software; you can redistribute it and/or modify it -- |
7 | 7 | -- under terms of the GNU General Public License as published by the Free -- |
|
45 | 45 | use type FS.File_Descriptor; |
46 | 46 | use type System.Address; |
47 | 47 | use type Interfaces.C.size_t; |
48 | | - Pid : Process_Id := 0; |
49 | | - Posix_Prio : GNATCOLL.OS.Libc.Priority; |
50 | | - FA : constant File_Actions := Init; |
51 | | - C_Cwd : Static_String_Builder (Cwd'Length + 1); |
52 | | - Old_Cwd : aliased Static_String_Builder (4096 + 1); |
53 | | - Status : Integer with Unreferenced; |
54 | | - C_Status : Libc_Status; |
55 | | - Spawn_Status : Integer; |
| 48 | + Pid : Process_Id := 0; |
| 49 | + Posix_Prio : GNATCOLL.OS.Libc.Priority; |
| 50 | + FA : constant File_Actions := Init; |
| 51 | + C_Cwd : Static_String_Builder (Cwd'Length + 1); |
| 52 | + Old_Cwd : aliased Static_String_Builder (4096 + 1); |
| 53 | + Status : Integer with Unreferenced; |
| 54 | + C_Status : Libc_Status; |
| 55 | + Spawn_Status : Integer; |
| 56 | + |
| 57 | + -- FD to close after dup2 calls. It's important to call the close |
| 58 | + -- otherwise some pipe might not be closed leading to hanging processes. |
| 59 | + |
| 60 | + FD_To_Close : array (1 .. 3) of FS.File_Descriptor := |
| 61 | + (others => FS.Invalid_FD); |
| 62 | + |
| 63 | + procedure Add_Potential_Close (FD : FS.File_Descriptor); |
| 64 | + pragma Inline (Add_Potential_Close); |
| 65 | + -- If necessary add a FD to the list of fd to close after the calls to |
| 66 | + -- dup2. |
| 67 | + |
| 68 | + ------------------------- |
| 69 | + -- Add_Potential_Close -- |
| 70 | + ------------------------- |
| 71 | + |
| 72 | + procedure Add_Potential_Close (FD : FS.File_Descriptor) is |
| 73 | + begin |
| 74 | + if FD = FS.Standin |
| 75 | + or else FD = FS.Standout |
| 76 | + or else FD = FS.Standerr |
| 77 | + then |
| 78 | + -- Never close standard descriptors |
| 79 | + return; |
| 80 | + end if; |
| 81 | + |
| 82 | + for Index in FD_To_Close'Range loop |
| 83 | + if FD = FD_To_Close (Index) then |
| 84 | + return; |
| 85 | + elsif FD_To_Close (Index) = FS.Invalid_FD then |
| 86 | + FD_To_Close (Index) := FD; |
| 87 | + return; |
| 88 | + end if; |
| 89 | + end loop; |
| 90 | + end Add_Potential_Close; |
| 91 | + |
56 | 92 | begin |
57 | | - -- Create file descriptors |
| 93 | + -- Internal_Spawn assume we have valid file descriptors passed as input |
| 94 | + -- (see gnatcoll-os-process.adb). Stdin, Stdout, Stderr cannot be |
| 95 | + -- Invalid_FD, To_Stdout or Null_FD (special values have been resolved |
| 96 | + -- by the caller). Nevertheless Stdin, Stdout and Stderr values might not |
| 97 | + -- all be distincts. |
58 | 98 |
|
59 | 99 | -- ??? Should we ignore the contents of Status below? |
| 100 | + |
60 | 101 | -- First issue dup2 directives |
61 | 102 | if Stdin /= FS.Standin then |
62 | 103 | Status := Add_Dup2 (FA, Stdin, FS.Standin); |
| 104 | + Add_Potential_Close (Stdin); |
63 | 105 | end if; |
64 | 106 |
|
65 | 107 | if Stdout /= FS.Standout then |
66 | 108 | Status := Add_Dup2 (FA, Stdout, FS.Standout); |
| 109 | + Add_Potential_Close (Stdout); |
67 | 110 | end if; |
68 | 111 |
|
69 | 112 | if Stderr /= FS.Standerr then |
70 | | - if Stderr = FS.To_Stdout then |
71 | | - Status := Add_Dup2 (FA, Stdout, FS.Standerr); |
72 | | - else |
73 | | - Status := Add_Dup2 (FA, Stderr, FS.Standerr); |
74 | | - end if; |
75 | | - end if; |
76 | | - |
77 | | - -- Then the close ones |
78 | | - if Stdin /= FS.Standin then |
79 | | - Status := Add_Close (FA, Stdin); |
| 113 | + Status := Add_Dup2 (FA, Stderr, FS.Standerr); |
| 114 | + Add_Potential_Close (Stderr); |
80 | 115 | end if; |
81 | 116 |
|
82 | | - if Stdout /= FS.Standout and then Stdout /= FS.Standin then |
83 | | - Status := Add_Close (FA, Stdout); |
84 | | - end if; |
85 | | - |
86 | | - if Stderr /= FS.Standout |
87 | | - and then Stderr /= FS.Standout |
88 | | - and then Stderr /= FS.Standin |
89 | | - then |
90 | | - Status := Add_Close (FA, Stderr); |
91 | | - end if; |
| 117 | + -- Then the close directives |
| 118 | + for Index in FD_To_Close'Range loop |
| 119 | + if FD_To_Close (Index) /= FS.Invalid_FD then |
| 120 | + Status := Add_Close (FA, FD_To_Close (Index)); |
| 121 | + end if; |
| 122 | + end loop; |
92 | 123 |
|
93 | 124 | -- Compute final priority |
94 | 125 | case Priority is |
|
0 commit comments