Hacked so that errno/intr error returns cause retries.

This commit is contained in:
shivers 1996-08-24 07:36:50 +00:00
parent 060badffa7
commit 996ee5db33
9 changed files with 75 additions and 56 deletions

View File

@ -179,12 +179,14 @@ int close_fdport(scheme_value port_data)
int fd = EXTRACT_FIXNUM(*PortData_Fd(port_data)); int fd = EXTRACT_FIXNUM(*PortData_Fd(port_data));
FILE *f = fstar_cache[fd]; FILE *f = fstar_cache[fd];
if( fclose(f) ) return errno;
*PortData_Fd(port_data) = SCHFALSE; *PortData_Fd(port_data) = SCHFALSE;
fdports[fd] = SCHFALSE; fdports[fd] = SCHFALSE;
*PortData_Closed(port_data) = SCHTRUE; *PortData_Closed(port_data) = SCHTRUE;
*PortData_Peek(port_data) = SCHFALSE; *PortData_Peek(port_data) = SCHFALSE;
fstar_cache[fd] = NULL; fstar_cache[fd] = NULL;
return fclose(f) ? errno : 0; return 0;
} }
else return EBADF; /* Already closed. */ else return EBADF; /* Already closed. */
} }
@ -202,17 +204,23 @@ static int cloexec_fdport(scheme_value port_data)
This is called right before an exec, which is sleazy; This is called right before an exec, which is sleazy;
we should have the port-revealing machinery set and reset we should have the port-revealing machinery set and reset
this value. this value.
If we get interrupted in the midst, we just bail out half-way.
The re-try loop will then have to repeat some work, but so what?
This whole function should go away.
*/ */
void cloexec_unrevealed(void) scheme_value cloexec_unrevealed(void)
{ {
int i; int i;
for(i=0; i<NUM_FDPORTS; i++) { for(i=0; i<NUM_FDPORTS; i++) {
scheme_value port = fdports[i]; scheme_value port = fdports[i];
if( port != SCHFALSE ) { if( port != SCHFALSE ) {
scheme_value data = *Port_PortData(port); scheme_value data = *Port_PortData(port);
if( *PortData_Rev(data) == 0 ) cloexec_fdport(data); if( *PortData_Rev(data) == 0 )
if( cloexec_fdport(data) == EINTR ) return ENTER_FIXNUM(EINTR);
} }
} }
return SCHFALSE;
} }
@ -329,7 +337,10 @@ void post_gc_fdports(void)
port, fd); port, fd);
fflush(stderr); fflush(stderr);
#endif #endif
if( rev == 0 ) close_fdport(*Port_PortData(port)); if( rev == 0 )
/* Close, even if interrupted -- GC's must be atomic. */
while( EINTR == close_fdport(*Port_PortData(port)) );
fdports[fd] = SCHFALSE; /* Drop the port. */ fdports[fd] = SCHFALSE; /* Drop the port. */
} }
} }
@ -340,12 +351,33 @@ void post_gc_fdports(void)
} }
#endif #endif
#define Min(a,b) (((a) < (b)) ? (a) : (b)) /* Not a function. */
/* Note the clearerr() call. This is so a ^D on a tty input stream
** doesn't shut the stream down forever. SunOS doesn't handle this according
** to POSIX spec, so we have to explicitly hack this case.
*/
static int read_stream_substring(scheme_value buf, int start, int end, FILE *f)
{
char *p = StrByte(buf,start);
int len = end-start;
clearerr(f);
/* If there's data in the buffer, use it. */
if (fbufcount(f) > 0)
return fread(p, 1, Min(len, fbufcount(f)), f);
/* Otherwise, do a read. */
return read(fileno(f), p, len);
}
#define MIN(a,b) (((a) < (b)) ? (a) : (b)) /* Not a function. */ #define MIN(a,b) (((a) < (b)) ? (a) : (b)) /* Not a function. */
int read_fdport_substring(scheme_value buf, int start, int end, scheme_value data) int read_fdport_substring(scheme_value buf, int start, int end, scheme_value data)
{ {
extern int read_stream_substring(scheme_value, int, int, FILE*);
scheme_value peek = *PortData_Peek(data); scheme_value peek = *PortData_Peek(data);
FILE *f = fstar_cache[EXTRACT_FIXNUM(*PortData_Fd(data))]; FILE *f = fstar_cache[EXTRACT_FIXNUM(*PortData_Fd(data))];
@ -368,11 +400,14 @@ int read_fdport_substring(scheme_value buf, int start, int end, scheme_value dat
return read_stream_substring(buf, start, end, f); return read_stream_substring(buf, start, end, f);
} }
/* We assume either fileno(f) does blocking i/o or f is unbuffered. */
int write_fdport_substring(scheme_value buf, int start, int end, scheme_value data) int write_fdport_substring(scheme_value buf, int start, int end, scheme_value data)
{ {
extern int write_stream_substring(scheme_value, int, int, FILE*);
FILE *f = fstar_cache[EXTRACT_FIXNUM(*PortData_Fd(data))]; FILE *f = fstar_cache[EXTRACT_FIXNUM(*PortData_Fd(data))];
return write_stream_substring(buf, start, end, f); int retval = fwrite(StrByte(buf,start), 1, end-start, f);
return ferror(f) ? -1 : retval; /* -1: error, 0: eof */
} }
/* 1st return value says why we terminated the read: /* 1st return value says why we terminated the read:

View File

@ -22,7 +22,7 @@ int set_fdbuf( scheme_value data, int policy, int bufsize );
int close_fdport(scheme_value port_data); int close_fdport(scheme_value port_data);
void cloexec_unrevealed(void); scheme_value cloexec_unrevealed(void);
int install_port(int fd, scheme_value port); int install_port(int fd, scheme_value port);

View File

@ -1,3 +1,5 @@
/* This code is all obsolete & should be thrown away. 8/23/96 Olin. */
#include <unistd.h> #include <unistd.h>
#include <sys/types.h> #include <sys/types.h>
#include <signal.h> #include <signal.h>

View File

@ -1,3 +1,4 @@
;;; The signal-handling code in the last half of this file is obsolete. 8/23/96
;;; Copyright (c) 1993 by Olin Shivers. ;;; Copyright (c) 1993 by Olin Shivers.
;;; Job control code. ;;; Job control code.

View File

@ -170,13 +170,16 @@
(if (fdport? port) (if (fdport? port)
;; Direct C support for Unix file ports -- zippy quick. ;; Direct C support for Unix file ports -- zippy quick.
(receive (terminator num-read) (let lp ((start start) (total 0))
(%read-delimited-fdport!/errno delims buf gobble? (receive (terminator num-read)
port start end) (%read-delimited-fdport!/errno delims buf gobble?
(if (integer? terminator) port start end)
(errno-error terminator %read-delimited! num-read (let ((total (+ num-read total)))
delims buf gobble? port start end) (cond ((not (integer? terminator)) (values terminator total))
(values terminator num-read))) ((= terminator errno/intr) (lp (+ start num-read) total))
(else (errno-error terminator %read-delimited!
num-read total
delims buf gobble? port start end))))))
;; This is the code for other kinds of ports. ;; This is the code for other kinds of ports.
;; Mighty slow -- we read each char twice (peek first, then read). ;; Mighty slow -- we read each char twice (peek first, then read).
@ -227,9 +230,12 @@
;; Direct C support for Unix file ports -- zippy quick. ;; Direct C support for Unix file ports -- zippy quick.
((fdport? port) ((fdport? port)
(receive (err num-read) (%skip-char-set-fdport/errno cset port) (let lp ((total 0))
(if err (errno-error err skip-char-set cset port num-read) (receive (err num-read) (%skip-char-set-fdport/errno cset port)
num-read))) (let ((total (+ total num-read)))
(cond ((not err) total)
((= errno/intr err) (lp total))
(errno-error err skip-char-set cset port total))))))
;; This is the code for other kinds of ports. ;; This is the code for other kinds of ports.
;; Mighty slow -- we read each char twice (peek first, then read). ;; Mighty slow -- we read each char twice (peek first, then read).

View File

@ -121,7 +121,7 @@ scheme_value set_sig_handler(int sig, scheme_value handler, int flags,
return ENTER_FIXNUM(-1); return ENTER_FIXNUM(-1);
} }
/* We may need this for ohandler later, but it may get clobbered when /* We may need this for ohandler later, but it may get clobbered
** when we set the new handler, so stash it away for now. ** when we set the new handler, so stash it away for now.
*/ */
old_scsh_handler = VECTOR_REF(Sinterrupt_handlersS, intnum); old_scsh_handler = VECTOR_REF(Sinterrupt_handlersS, intnum);

View File

@ -1042,11 +1042,14 @@ scheme_value df_init_fdports(long nargs, scheme_value *args)
scheme_value df_cloexec_unrevealed(long nargs, scheme_value *args) scheme_value df_cloexec_unrevealed(long nargs, scheme_value *args)
{ {
extern void cloexec_unrevealed(void); extern scheme_value cloexec_unrevealed(void);
scheme_value ret1;
scheme_value r1;
cig_check_nargs(0, nargs, "cloexec_unrevealed"); cig_check_nargs(0, nargs, "cloexec_unrevealed");
cloexec_unrevealed(); r1 = cloexec_unrevealed();
return SCHFALSE; ret1 = r1;
return ret1;
} }
scheme_value df_install_port(long nargs, scheme_value *args) scheme_value df_install_port(long nargs, scheme_value *args)

View File

@ -1021,7 +1021,11 @@
(define-foreign %init-fdports! (init_fdports) ignore) (define-foreign %init-fdports! (init_fdports) ignore)
(define-foreign cloexec-unrevealed-ports (cloexec_unrevealed) ignore) (define-foreign %cloexec-unrevealed-ports (cloexec_unrevealed) desc)
(define (cloexec-unrevealed-ports)
;; Loop if interrupted.
(and (%cloexec-unrevealed-ports) (cloexec-unrevealed-ports)))
(define-foreign %install-port/errno (define-foreign %install-port/errno
(install_port (integer fd) (desc port)) (install_port (integer fd) (desc port))

View File

@ -261,43 +261,11 @@ int read_fdes_substring(scheme_value buf, int start, int end, int fd)
return read(fd, StrByte(buf,start), end-start); return read(fd, StrByte(buf,start), end-start);
} }
#define Min(a,b) (((a) < (b)) ? (a) : (b)) /* Not a function. */
/* Note the clearerr() call. This is so a ^D on a tty input stream
** doesn't shut the stream down forever. SunOS doesn't handle this according
** to POSIX spec, so we have to explicitly hack this case.
*/
int read_stream_substring(scheme_value buf, int start, int end, FILE *f)
{
char *p = StrByte(buf,start);
int len = end-start;
clearerr(f);
/* If there's data in the buffer, use it. */
if (fbufcount(f) > 0)
return fread(p, 1, Min(len, fbufcount(f)), f);
/* Otherwise, do a read. */
return read(fileno(f), p, len);
}
int write_fdes_substring(scheme_value buf, int start, int end, int fd) int write_fdes_substring(scheme_value buf, int start, int end, int fd)
{ {
return write(fd, StrByte(buf,start), end-start); return write(fd, StrByte(buf,start), end-start);
} }
/* We assume either fileno(f) does blocking i/o or f is unbuffered. */
int write_stream_substring(scheme_value buf, int start, int end, FILE *f)
{
int retval = fwrite(StrByte(buf,start), 1, end-start, f);
return ferror(f) ? -1 : retval; /* -1: error, 0: eof */
}
/* /*
** Stat hackery ** Stat hackery