]> Repositorios git - scryer-prolog.git/commitdiff
launch exception if closing a closed TCP stream #1046
authorAdrián Arroyo Calle <[email protected]>
Tue, 28 Sep 2021 20:48:51 +0000 (22:48 +0200)
committerAdrián Arroyo Calle <[email protected]>
Tue, 28 Sep 2021 20:48:51 +0000 (22:48 +0200)
src/machine/streams.rs
src/machine/system_calls.rs

index e8507f134fca256fa4ea096984cc0a6b270082cd..d765d8817e5f6be00b74983ec44bdbf100ce7b59 100644 (file)
@@ -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)
index ade423a16540f7dfd21bd86d7eab9390d3cf343f..e14a530f461be992f2425779e242204abb0ff983 100644 (file)
@@ -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);
+                        }
                     }
                 }
             }