guile-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Guile-commits] 02/02: GC of non-blocking port does not block


From: Andy Wingo
Subject: [Guile-commits] 02/02: GC of non-blocking port does not block
Date: Wed, 31 Aug 2016 17:33:07 +0000 (UTC)

wingo pushed a commit to branch master
in repository guile.

commit b733ca461ce03c6daeadca0f2eb4da13ccdd2930
Author: Andy Wingo <address@hidden>
Date:   Wed Aug 31 19:31:12 2016 +0200

    GC of non-blocking port does not block
    
    * libguile/ports.h (SCM_F_PORT_FINALIZING)
      (SCM_PORT_FINALIZING_P, SCM_SET_PORT_FINALIZING): New private
      definitions.
    * libguile/ports.c (finalize_port): Set the port-finalizing flag.
      (scm_i_write_bytes): If the port is finalizing but output returned
      EWOULDBLOCK, warn and discard the output.
---
 libguile/ports.c |   27 ++++++++++++++++++++++++++-
 libguile/ports.h |   19 ++++++++++++++-----
 2 files changed, 40 insertions(+), 6 deletions(-)

diff --git a/libguile/ports.c b/libguile/ports.c
index 278bbe9..1209b43 100644
--- a/libguile/ports.c
+++ b/libguile/ports.c
@@ -691,6 +691,7 @@ finalize_port (void *ptr, void *data)
 
   if (SCM_OPENP (port))
     {
+      SCM_SET_PORT_FINALIZING (port);
       scm_internal_catch (SCM_BOOL_T, do_close, ptr,
                           scm_handle_by_message_noexit, NULL);
       scm_gc_ports_collected++;
@@ -2797,7 +2798,31 @@ scm_i_write_bytes (SCM port, SCM src, size_t start, 
size_t count)
       size_t ret = ptob->c_write (port, src, start + written, count - written);
 
       if (ret == (size_t) -1)
-        port_poll (port, POLLOUT, -1);
+        {
+          if (SCM_PORT_FINALIZING_P (port))
+            {
+              /* This port is being closed because it became unreachable
+                 and was finalized, but it has buffered output, and the
+                 resource is not currently writable.  Instead of
+                 blocking, discard buffered output and warn.  To avoid
+                 this situation, force-output on the port before letting
+                 it go!  */
+              scm_puts
+                ("Warning: Discarding buffered output on non-blocking port\n"
+                 "         ",
+                 scm_current_warning_port ());
+              scm_display (port, scm_current_warning_port());
+              scm_puts
+                ("\n"
+                 "         closed by the garbage collector.  To avoid this\n"
+                 "         behavior and this warning, call `force-output' or\n"
+                 "         `close-port' on the port before letting go of 
it.\n",
+                 scm_current_warning_port ());
+              break;
+            }
+          else
+            port_poll (port, POLLOUT, -1);
+        }
       else
         written += ret;
     }
diff --git a/libguile/ports.h b/libguile/ports.h
index 6fe9ecd..93a1a59 100644
--- a/libguile/ports.h
+++ b/libguile/ports.h
@@ -52,11 +52,14 @@ SCM_INTERNAL SCM scm_i_port_weak_set;
    there is a flag indicating whether the port is open or not, and then
    some "mode bits": flags indicating whether the port is an input
    and/or an output port and how Guile should buffer the port.  */
-#define SCM_OPN                (1U<<16) /* Is the port open? */
-#define SCM_RDNG       (1U<<17) /* Is it a readable port? */
-#define SCM_WRTNG      (1U<<18) /* Is it writable? */
-#define SCM_BUF0       (1U<<19) /* Is it unbuffered? */
-#define SCM_BUFLINE     (1U<<20) /* Is it line-buffered? */
+#define SCM_OPN                (1U<<8) /* Is the port open? */
+#define SCM_RDNG       (1U<<9) /* Is it a readable port? */
+#define SCM_WRTNG      (1U<<10) /* Is it writable? */
+#define SCM_BUF0       (1U<<11) /* Is it unbuffered? */
+#define SCM_BUFLINE     (1U<<12) /* Is it line-buffered? */
+#ifdef BUILDING_LIBGUILE
+#define SCM_F_PORT_FINALIZING (1U<<13) /* Port is being closed via GC. */
+#endif
 
 #define SCM_PORTP(x) (SCM_HAS_TYP7 (x, scm_tc7_port))
 #define SCM_OPPORTP(x) (SCM_PORTP (x) && (SCM_CELL_WORD_0 (x) & SCM_OPN))
@@ -68,6 +71,12 @@ SCM_INTERNAL SCM scm_i_port_weak_set;
 #define SCM_CLOSEDP(x) (!SCM_OPENP (x))
 #define SCM_CLR_PORT_OPEN_FLAG(p) \
   SCM_SET_CELL_WORD_0 ((p), SCM_CELL_WORD_0 (p) & ~SCM_OPN)
+#ifdef BUILDING_LIBGUILE
+#define SCM_PORT_FINALIZING_P(x) \
+  (SCM_CELL_WORD_0 (x) & SCM_F_PORT_FINALIZING)
+#define SCM_SET_PORT_FINALIZING(p) \
+  SCM_SET_CELL_WORD_0 ((p), SCM_CELL_WORD_0 (p) | SCM_F_PORT_FINALIZING)
+#endif
 
 typedef struct scm_t_port_type scm_t_port_type;
 typedef struct scm_t_port scm_t_port;



reply via email to

[Prev in Thread] Current Thread [Next in Thread]