Pass host-generated SIGPIPE to libos
Socket-related ocalls, e.g, sendto, sendmsg and write, may cause SIGPIPE in host. Since the ocall is called by libos, this kind of signal should be handled in libos. We ignore SIGPIPE in host and raise the same signal in libos if the return value of the above ocalls is EPIPE. In this way the signal is handled by libos.
This commit is contained in:
parent
44583e15be
commit
5d5e8d44ec
@ -51,3 +51,20 @@ macro_rules! try_libc {
|
||||
ret
|
||||
}};
|
||||
}
|
||||
|
||||
// return Err(errno) if libc return -1
|
||||
// raise SIGPIPE if errno == EPIPE
|
||||
macro_rules! try_libc_may_epipe {
|
||||
($ret: expr) => {{
|
||||
let ret = unsafe { $ret };
|
||||
if ret < 0 {
|
||||
let errno = unsafe { libc::errno() };
|
||||
if errno == Errno::EPIPE as i32 {
|
||||
// SIGPIPE = 12
|
||||
crate::signal::do_tkill(current!().tid(), 12);
|
||||
}
|
||||
return_errno!(Errno::from(errno as u32), "libc error");
|
||||
}
|
||||
ret
|
||||
}};
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ impl File for SocketFile {
|
||||
|
||||
fn write(&self, buf: &[u8]) -> Result<usize> {
|
||||
let (buf_ptr, buf_len) = buf.as_ptr_and_len();
|
||||
let ret = try_libc!(libc::ocall::write(
|
||||
let ret = try_libc_may_epipe!(libc::ocall::write(
|
||||
self.host_fd,
|
||||
buf_ptr as *const c_void,
|
||||
buf_len
|
||||
|
@ -56,10 +56,10 @@ impl SocketFile {
|
||||
let (msg_control, msg_controllen) = control.as_ptr_and_len();
|
||||
let msg_control = msg_control as *const c_void;
|
||||
// Flags
|
||||
let flags = flags.bits();
|
||||
let raw_flags = flags.bits();
|
||||
|
||||
let bytes_sent = try_libc!({
|
||||
// Do OCall
|
||||
// Do OCall
|
||||
unsafe {
|
||||
let status = occlum_ocall_sendmsg(
|
||||
&mut retval as *mut isize,
|
||||
host_fd,
|
||||
@ -69,12 +69,17 @@ impl SocketFile {
|
||||
msg_iovlen,
|
||||
msg_control,
|
||||
msg_controllen,
|
||||
flags,
|
||||
raw_flags,
|
||||
);
|
||||
assert!(status == sgx_status_t::SGX_SUCCESS);
|
||||
}
|
||||
|
||||
let bytes_sent = if flags.contains(SendFlags::MSG_NOSIGNAL) {
|
||||
try_libc!(retval)
|
||||
} else {
|
||||
try_libc_may_epipe!(retval)
|
||||
};
|
||||
|
||||
retval
|
||||
});
|
||||
debug_assert!(bytes_sent >= 0);
|
||||
Ok(bytes_sent as usize)
|
||||
}
|
||||
|
@ -286,7 +286,7 @@ pub fn do_sendto(
|
||||
let file_ref = current!().file(fd as FileDesc)?;
|
||||
if let Ok(socket) = file_ref.as_socket() {
|
||||
// TODO: check addr and addr_len according to connection mode
|
||||
let ret = try_libc!(libc::ocall::sendto(
|
||||
let ret = try_libc_may_epipe!(libc::ocall::sendto(
|
||||
socket.fd(),
|
||||
base,
|
||||
len,
|
||||
|
@ -36,12 +36,10 @@ int occlum_pal_init(const struct occlum_pal_attr *attr) {
|
||||
errno = EEXIST;
|
||||
return -1;
|
||||
}
|
||||
// FIXME
|
||||
#ifndef SGX_MODE_SIM
|
||||
|
||||
if (pal_register_sig_handlers() < 0) {
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (pal_init_enclave(resolved_path) < 0) {
|
||||
return -1;
|
||||
|
@ -7,12 +7,16 @@
|
||||
#define SIGRT_INTERRUPT 64
|
||||
|
||||
int pal_register_sig_handlers(void) {
|
||||
struct sigaction action;
|
||||
action.sa_handler = SIG_IGN;
|
||||
memset(&action.sa_mask, 0, sizeof(action.sa_mask));
|
||||
action.sa_flags = 0;
|
||||
if (sigaction(SIGRT_INTERRUPT, &action, NULL) < 0) {
|
||||
PAL_ERROR("Failed to regiter signal handlers");
|
||||
// FIXME: enable interruptable signal in SIM mode
|
||||
#ifndef SGX_MODE_SIM
|
||||
if (signal(SIGRT_INTERRUPT, SIG_IGN) == SIG_ERR) {
|
||||
PAL_ERROR("Failed to regiter the SIG64 handler");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
|
||||
PAL_ERROR("Failed to regiter the SIGPIPE handler");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
|
Loading…
Reference in New Issue
Block a user