@@ -67,24 +67,39 @@ markCloseOnExec(int fd)
6767 return 0 ;
6868}
6969
70+ #if !defined(_AIX )
71+ /* The /proc file system on AIX does not contain open system files
72+ * like /dev/random. Therefore we use a different approach and do
73+ * not need isAsciiDigit() or FD_DIR */
7074static int
7175isAsciiDigit (char c )
7276{
7377 return c >= '0' && c <= '9' ;
7478}
7579
76- #if defined(_AIX )
77- /* AIX does not understand '/proc/self' - it requires the real process ID */
78- #define FD_DIR aix_fd_dir
79- #elif defined(_ALLBSD_SOURCE )
80- #define FD_DIR "/dev/fd"
81- #else
82- #define FD_DIR "/proc/self/fd"
80+ #if defined(_ALLBSD_SOURCE )
81+ #define FD_DIR "/dev/fd"
82+ #else
83+ #define FD_DIR "/proc/self/fd"
84+ #endif
8385#endif
8486
8587static int
8688markDescriptorsCloseOnExec (void )
8789{
90+ #if defined(_AIX )
91+ /* On AIX, we cannot rely on proc file system iteration to find all open files. Since
92+ * iteration over all possible file descriptors, and subsequently closing them, can
93+ * take a very long time, we use a bulk close via `ioctl` that is available on AIX.
94+ * Since we hard-close, we need to make sure to keep the fail pipe file descriptor
95+ * alive until the exec call. Therefore we mark the fail pipe fd with close on exec
96+ * like the other OSes do, but then proceed to hard-close file descriptors beyond that.
97+ */
98+ if (fcntl (FAIL_FILENO + 1 , F_CLOSEM , 0 ) == -1 ||
99+ (markCloseOnExec (FAIL_FILENO ) == -1 && errno != EBADF )) {
100+ return -1 ;
101+ }
102+ #else
88103 DIR * dp ;
89104 struct dirent * dirp ;
90105 /* This function marks all file descriptors beyond stderr as CLOEXEC.
@@ -93,12 +108,6 @@ markDescriptorsCloseOnExec(void)
93108 * execve. */
94109 const int fd_from = STDERR_FILENO + 1 ;
95110
96- #if defined(_AIX )
97- /* AIX does not understand '/proc/self' - it requires the real process ID */
98- char aix_fd_dir [32 ]; /* the pid has at most 19 digits */
99- snprintf (aix_fd_dir , 32 , "/proc/%d/fd" , getpid ());
100- #endif
101-
102111 if ((dp = opendir (FD_DIR )) == NULL )
103112 return -1 ;
104113
@@ -114,6 +123,7 @@ markDescriptorsCloseOnExec(void)
114123 }
115124
116125 closedir (dp );
126+ #endif
117127
118128 return 0 ;
119129}
@@ -406,6 +416,10 @@ childProcess(void *arg)
406416 /* We moved the fail pipe fd */
407417 fail_pipe_fd = FAIL_FILENO ;
408418
419+ /* For AIX: The code in markDescriptorsCloseOnExec() relies on the current
420+ * semantic of this function. When this point here is reached only the
421+ * FDs 0,1,2 and 3 are further used until the exec() or the exit(-1). */
422+
409423 /* close everything */
410424 if (markDescriptorsCloseOnExec () == -1 ) { /* failed, close the old way */
411425 int max_fd = (int )sysconf (_SC_OPEN_MAX );
0 commit comments