mirror of
https://github.com/fish-shell/fish-shell.git
synced 2024-11-22 12:41:08 +08:00
parent
ea980c19db
commit
ac9c5ed1b2
19
src/fds.rs
19
src/fds.rs
|
@ -1,9 +1,11 @@
|
|||
use crate::common::wcs2zstring;
|
||||
use crate::flog::FLOG;
|
||||
use crate::signal::signal_check_cancel;
|
||||
#[cfg(test)]
|
||||
use crate::tests::prelude::*;
|
||||
use crate::wchar::prelude::*;
|
||||
use crate::wutil::perror;
|
||||
use errno::{errno, set_errno};
|
||||
use libc::{
|
||||
c_int, EINTR, FD_CLOEXEC, F_DUPFD_CLOEXEC, F_GETFD, F_GETFL, F_SETFD, F_SETFL, O_CLOEXEC,
|
||||
O_NONBLOCK,
|
||||
|
@ -228,7 +230,22 @@ pub fn wopen_cloexec(pathname: &wstr, flags: i32, mode: libc::c_int) -> RawFd {
|
|||
pub fn open_cloexec(path: &CStr, flags: i32, mode: libc::c_int) -> RawFd {
|
||||
// Port note: the C++ version of this function had a fallback for platforms where
|
||||
// O_CLOEXEC is not supported, using fcntl. In 2023, this is no longer needed.
|
||||
unsafe { libc::open(path.as_ptr(), flags | O_CLOEXEC, mode) }
|
||||
let saved_errno = errno();
|
||||
errno::set_errno(errno::Errno(0));
|
||||
// We retry this in case of signals,
|
||||
// if we get EINTR and it's not a SIGINIT, we continue.
|
||||
// If it is that's our cancel signal, so we abort.
|
||||
loop {
|
||||
let ret = unsafe { libc::open(path.as_ptr(), flags | O_CLOEXEC, mode) };
|
||||
if ret >= 0 {
|
||||
set_errno(saved_errno);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if errno::errno().0 != EINTR || signal_check_cancel() != 0 {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Close a file descriptor \p fd, retrying on EINTR.
|
||||
|
|
|
@ -663,12 +663,12 @@ impl IoChain {
|
|||
FLOGF!(warning, NOCLOB_ERROR, spec.target);
|
||||
} else {
|
||||
if should_flog!(warning) {
|
||||
FLOGF!(warning, FILE_ERROR, spec.target);
|
||||
let err = errno::errno().0;
|
||||
// If the error is that the file doesn't exist
|
||||
// or there's a non-directory component,
|
||||
// find the first problematic component for a better message.
|
||||
if [ENOENT, ENOTDIR].contains(&err) {
|
||||
FLOGF!(warning, FILE_ERROR, spec.target);
|
||||
let mut dname: &wstr = &spec.target;
|
||||
while !dname.is_empty() {
|
||||
let next: &wstr = wdirname(dname);
|
||||
|
@ -686,7 +686,11 @@ impl IoChain {
|
|||
}
|
||||
dname = next;
|
||||
}
|
||||
} else {
|
||||
} else if err != EINTR {
|
||||
// If we get EINTR we had a cancel signal.
|
||||
// That's expected (ctrl-c on the commandline),
|
||||
// so no warning.
|
||||
FLOGF!(warning, FILE_ERROR, spec.target);
|
||||
perror("open");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,6 +63,15 @@ subprocess.call(["pkill", "-TERM", "-P", str(sp.spawn.pid), "sleep"])
|
|||
expect_str("fish_kill_signal 15")
|
||||
expect_prompt()
|
||||
|
||||
# See that open() is only interruptible by SIGINT.
|
||||
sendline("mkfifo fifoo")
|
||||
expect_prompt()
|
||||
sendline("cat >fifoo")
|
||||
subprocess.call(["kill", "-WINCH", str(sp.spawn.pid)])
|
||||
expect_re("open: ", shouldfail=True, timeout=10)
|
||||
subprocess.call(["kill", "-INT", str(sp.spawn.pid)])
|
||||
expect_prompt()
|
||||
|
||||
# Verify that sending SIGHUP to the shell, such as will happen when the tty is
|
||||
# closed by the terminal, terminates the shell and the foreground command and
|
||||
# any background commands run from that shell.
|
||||
|
|
Loading…
Reference in New Issue
Block a user