Clean up how pipe fd avoidance works

fish has to ensure that the pipes it creates do not conflict with any
explicit fds named in redirections. Switch this code to using
autoclose_fd_t to make the ownership logic more explicit, and also
introduce fd_set_t to reduce the dependence on io_chain_t.
This commit is contained in:
ridiculousfish
2019-12-12 14:42:03 -08:00
parent 4e52feb51a
commit be685faeb8
5 changed files with 104 additions and 94 deletions

View File

@@ -24,8 +24,8 @@ maybe_t<dup2_list_t> dup2_list_t::resolve_chain(const io_chain_t &io_chain) {
// Here we definitely do not want to set CLO_EXEC because our child needs access.
// Open the file.
const io_file_t *io_file = static_cast<const io_file_t *>(io_ref.get());
int file_fd = wopen(io_file->filename, io_file->flags, OPEN_MASK);
if (file_fd < 0) {
autoclose_fd_t file_fd{wopen(io_file->filename, io_file->flags, OPEN_MASK)};
if (!file_fd.valid()) {
if ((io_file->flags & O_EXCL) && (errno == EEXIST)) {
debug(1, NOCLOB_ERROR, io_file->filename.c_str());
} else {
@@ -38,22 +38,23 @@ maybe_t<dup2_list_t> dup2_list_t::resolve_chain(const io_chain_t &io_chain) {
// If by chance we got the file we want, we're done. Otherwise move the fd to an
// unused place and dup2 it.
// Note move_fd_to_unused() will close the incoming file_fd.
if (file_fd != io_file->fd) {
file_fd = move_fd_to_unused(file_fd, io_chain, false /* cloexec */);
if (file_fd < 0) {
if (file_fd.fd() != io_file->fd) {
file_fd = move_fd_to_unused(std::move(file_fd), io_chain.fd_set(),
false /* cloexec */);
if (!file_fd.valid()) {
debug(1, FILE_ERROR, io_file->filename.c_str());
if (should_debug(1)) wperror(L"dup");
return none();
}
}
// Record that we opened this file, so we will auto-close it.
assert(file_fd >= 0 && "Should have a valid file_fd");
result.opened_fds_.emplace_back(file_fd);
assert(file_fd.valid() && "Should have a valid file_fd");
// Mark our dup2 and our close actions.
result.add_dup2(file_fd, io_file->fd);
result.add_close(file_fd);
result.add_dup2(file_fd.fd(), io_file->fd);
result.add_close(file_fd.fd());
// Store our file.
result.opened_fds_.push_back(std::move(file_fd));
break;
}