fix file-stream read/write on concurrent close
Includes repairs for both Racket CS and traditional Racket.
This commit is contained in:
parent
2799713ea5
commit
89403dc8cd
|
@ -1166,6 +1166,68 @@
|
||||||
(peek-bytes 1 end i)))))
|
(peek-bytes 1 end i)))))
|
||||||
(delete-file tempfilename))
|
(delete-file tempfilename))
|
||||||
|
|
||||||
|
;;------------------------------------------------------------
|
||||||
|
;; File-stream ports and blocking behavior
|
||||||
|
|
||||||
|
(let ()
|
||||||
|
(define-values (s i o e) (subprocess #f #f #f (find-exe) "-e" "(read)"))
|
||||||
|
|
||||||
|
(thread (lambda ()
|
||||||
|
(sync (system-idle-evt))
|
||||||
|
(close-input-port i)))
|
||||||
|
|
||||||
|
(err/rt-test
|
||||||
|
(peek-bytes-avail! (make-bytes 10) 0 #f i)
|
||||||
|
exn:fail?)
|
||||||
|
|
||||||
|
(close-output-port o)
|
||||||
|
(close-input-port e)
|
||||||
|
(subprocess-wait s))
|
||||||
|
|
||||||
|
(let ()
|
||||||
|
(define-values (s i o e) (subprocess #f #f #f (find-exe) "-e" "(read)"))
|
||||||
|
|
||||||
|
(thread (lambda ()
|
||||||
|
(sync (system-idle-evt))
|
||||||
|
(close-input-port i)))
|
||||||
|
|
||||||
|
(test 0 peek-bytes-avail! (make-bytes 10) 0 (port-progress-evt i) i)
|
||||||
|
|
||||||
|
(close-output-port o)
|
||||||
|
(close-input-port e)
|
||||||
|
(subprocess-wait s))
|
||||||
|
|
||||||
|
(let ()
|
||||||
|
(define-values (s i o e) (subprocess #f #f #f (find-exe) "-e" "(read)"))
|
||||||
|
|
||||||
|
(thread (lambda ()
|
||||||
|
(sync (system-idle-evt))
|
||||||
|
(close-input-port i)))
|
||||||
|
|
||||||
|
;; Short not get stuck:
|
||||||
|
(sync (port-progress-evt i))
|
||||||
|
|
||||||
|
(close-output-port o)
|
||||||
|
(close-input-port e)
|
||||||
|
(subprocess-wait s))
|
||||||
|
|
||||||
|
(let ()
|
||||||
|
(define-values (s i o e) (subprocess #f #f #f (find-exe) "-e" "(let loop () (write-bytes (make-bytes 1024)) (loop))"))
|
||||||
|
|
||||||
|
(thread (lambda ()
|
||||||
|
(sync (system-idle-evt))
|
||||||
|
(close-output-port o)))
|
||||||
|
|
||||||
|
(err/rt-test
|
||||||
|
(let loop ()
|
||||||
|
(write-bytes-avail #"hello" o)
|
||||||
|
(loop))
|
||||||
|
exn:fail?)
|
||||||
|
|
||||||
|
(close-input-port i)
|
||||||
|
(close-input-port e)
|
||||||
|
(subprocess-wait s))
|
||||||
|
|
||||||
;;------------------------------------------------------------
|
;;------------------------------------------------------------
|
||||||
|
|
||||||
;; Test custom output port
|
;; Test custom output port
|
||||||
|
|
|
@ -36,7 +36,8 @@
|
||||||
[close-peek-buffer
|
[close-peek-buffer
|
||||||
(lambda ()
|
(lambda ()
|
||||||
(purge-buffer)
|
(purge-buffer)
|
||||||
(set! bstr #""))]
|
(set! bstr #"")
|
||||||
|
(progress!))]
|
||||||
|
|
||||||
[buffer-adjust-pos
|
[buffer-adjust-pos
|
||||||
(lambda (i)
|
(lambda (i)
|
||||||
|
|
|
@ -5174,6 +5174,8 @@ fd_flush_done(Scheme_Object *port)
|
||||||
|
|
||||||
op = scheme_output_port_record(port);
|
op = scheme_output_port_record(port);
|
||||||
|
|
||||||
|
if (op->closed) return 1;
|
||||||
|
|
||||||
fop = (Scheme_FD *)op->port_data;
|
fop = (Scheme_FD *)op->port_data;
|
||||||
|
|
||||||
return !fop->flushing;
|
return !fop->flushing;
|
||||||
|
@ -5296,6 +5298,9 @@ static intptr_t flush_fd(Scheme_Output_Port *op,
|
||||||
(Scheme_Object *)op, 0.0,
|
(Scheme_Object *)op, 0.0,
|
||||||
enable_break);
|
enable_break);
|
||||||
END_ESCAPEABLE();
|
END_ESCAPEABLE();
|
||||||
|
|
||||||
|
if (op->closed)
|
||||||
|
return 0;
|
||||||
} else if (len == RKTIO_WRITE_ERROR) {
|
} else if (len == RKTIO_WRITE_ERROR) {
|
||||||
if (consume_buffer) {
|
if (consume_buffer) {
|
||||||
/* Drop unsuccessfully flushed bytes. This isn't the
|
/* Drop unsuccessfully flushed bytes. This isn't the
|
||||||
|
@ -5448,12 +5453,15 @@ fd_close_output(Scheme_Output_Port *port)
|
||||||
if (fop->bufcount)
|
if (fop->bufcount)
|
||||||
flush_fd(port, NULL, 0, 0, 0, 0);
|
flush_fd(port, NULL, 0, 0, 0, 0);
|
||||||
|
|
||||||
if (fop->flushing && !scheme_force_port_closed)
|
if (fop->flushing && fop->bufcount && !scheme_force_port_closed) {
|
||||||
wait_until_fd_flushed(port, 0);
|
wait_until_fd_flushed(port, 0);
|
||||||
|
if (port->closed)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!scheme_force_port_closed && fop->fd) {
|
if (!scheme_force_port_closed && fop->fd) {
|
||||||
/* Check for flushing at the rktio level (not to be confused
|
/* Check for flushing at the rktio level (not to be confused
|
||||||
with pulmber flushes): */
|
with plumber flushes): */
|
||||||
while (!rktio_poll_write_flushed(scheme_rktio, fop->fd)) {
|
while (!rktio_poll_write_flushed(scheme_rktio, fop->fd)) {
|
||||||
scheme_block_until(end_fd_flush_done, end_fd_flush_needs_wakeup, (Scheme_Object *)fop, 0.0);
|
scheme_block_until(end_fd_flush_done, end_fd_flush_needs_wakeup, (Scheme_Object *)fop, 0.0);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user