| 1138 | #endif |
| 1139 | |
| 1140 | static int cbm_subprocess_spawn_posix(cbm_subprocess_t *process) { |
| 1141 | int input_flags = O_RDONLY; |
| 1142 | #ifdef O_CLOEXEC |
| 1143 | input_flags |= O_CLOEXEC; |
| 1144 | #endif |
| 1145 | int input = cbm_posix_fd_at_least_three(open("/dev/null", input_flags)); |
| 1146 | const char *target = process->log_file ? process->log_file : "/dev/null"; |
| 1147 | int output_flags = O_WRONLY | O_CREAT | O_TRUNC; |
| 1148 | #ifdef O_CLOEXEC |
| 1149 | output_flags |= O_CLOEXEC; |
| 1150 | #endif |
| 1151 | #ifdef O_NOFOLLOW |
| 1152 | output_flags |= O_NOFOLLOW; |
| 1153 | #endif |
| 1154 | int output = cbm_posix_fd_at_least_three(open(target, output_flags, 0600)); |
| 1155 | if (input < 0 || output < 0) { |
| 1156 | if (input >= 0) { |
| 1157 | (void)close(input); |
| 1158 | } |
| 1159 | if (output >= 0) { |
| 1160 | (void)close(output); |
| 1161 | } |
| 1162 | return -1; |
| 1163 | } |
| 1164 | struct stat output_status; |
| 1165 | if (fstat(output, &output_status) != 0 || |
| 1166 | (process->log_file && !S_ISREG(output_status.st_mode))) { |
| 1167 | (void)close(input); |
| 1168 | (void)close(output); |
| 1169 | return -1; |
| 1170 | } |
| 1171 | if (process->log_file && fchmod(output, 0600) != 0) { |
| 1172 | (void)close(input); |
| 1173 | (void)close(output); |
| 1174 | return -1; |
| 1175 | } |
| 1176 | |
| 1177 | long max_fd = sysconf(_SC_OPEN_MAX); |
| 1178 | if (max_fd < 0 || max_fd > 1048576L) { |
| 1179 | max_fd = 65536L; |
| 1180 | } |
| 1181 | |
| 1182 | pid_t pid = -1; |
| 1183 | #ifdef __APPLE__ |
| 1184 | int spawn_rc = cbm_posix_spawn_apple(process, input, output, &pid); |
| 1185 | for (int attempt = 0; spawn_rc == CBM_SPAWN_RETRY && attempt < CBM_SPAWN_RETRY_ATTEMPTS; |
| 1186 | attempt++) { |
| 1187 | cbm_spawn_backoff(attempt); |
| 1188 | spawn_rc = cbm_posix_spawn_apple(process, input, output, &pid); |
| 1189 | } |
| 1190 | if (spawn_rc == CBM_SPAWN_RETRY) { |
| 1191 | spawn_rc = -1; /* still exhausted after backoff: a real failure */ |
| 1192 | } |
| 1193 | if (spawn_rc < 0) { |
| 1194 | (void)close(input); |
| 1195 | (void)close(output); |
| 1196 | return -1; |
| 1197 | } |
no test coverage detected