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