mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-05-20 11:40:18 +02:00
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.
This commit is contained in:
parent
b8a53b98b3
commit
b733ca461c
2 changed files with 40 additions and 6 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue