From: Adrián Arroyo Calle Date: Tue, 28 Sep 2021 20:48:51 +0000 (+0200) Subject: launch exception if closing a closed TCP stream #1046 X-Git-Tag: v0.9.0~40^2~4 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=4d0998ef72b02d1f962b65e17311c7b66123323c;p=scryer-prolog.git launch exception if closing a closed TCP stream #1046 --- diff --git a/src/machine/streams.rs b/src/machine/streams.rs index e8507f13..d765d881 100644 --- a/src/machine/streams.rs +++ b/src/machine/streams.rs @@ -164,10 +164,10 @@ impl Drop for StreamInstance { fn drop(&mut self) { match self { StreamInstance::TcpStream(_, ref mut tcp_stream) => { - tcp_stream.shutdown(Shutdown::Both).unwrap(); + tcp_stream.shutdown(Shutdown::Both).unwrap_or(()) } StreamInstance::TlsStream(_, ref mut tls_stream) => { - tls_stream.shutdown().unwrap(); + tls_stream.shutdown().unwrap_or(()); } _ => {} } @@ -636,6 +636,20 @@ impl Stream { } } + pub(crate) fn is_closed(&self) -> bool { + match self.stream_inst.0.borrow_mut().stream_inst { + StreamInstance::Null => true, + StreamInstance::TcpStream(_, ref mut tcp_stream) => { + let mut buf = [0;8]; + match tcp_stream.peek(&mut buf) { + Ok(n_bytes) => n_bytes == 0, + Err(_) => true + } + }, + _ => false + } + } + fn unpause_stream(&mut self) { let stream_inst = match self.stream_inst.0.borrow_mut().stream_inst { StreamInstance::PausedPrologStream(ref put_back, ref mut stream_inst) diff --git a/src/machine/system_calls.rs b/src/machine/system_calls.rs index ade423a1..e14a530f 100644 --- a/src/machine/system_calls.rs +++ b/src/machine/system_calls.rs @@ -2704,10 +2704,29 @@ impl MachineState { } if !stream.is_stdin() && !stream.is_stdout() && !stream.is_stderr() { - stream.close(); + if stream.is_closed() { + let stub = MachineError::functor_stub( + clause_name!("close"), + 1, + ); + + let addr = self.heap.to_unifiable( + HeapCellValue::Stream(stream.clone()), + ); - if let Some(ref alias) = stream.options().alias { - indices.stream_aliases.remove(alias); + return Err(self.error_form( + MachineError::existence_error( + self.heap.h(), + ExistenceError::Stream(addr), + ), + stub, + )); + } else { + stream.close(); + + if let Some(ref alias) = stream.options().alias { + indices.stream_aliases.remove(alias); + } } } }