ref: 48b0c10681bb4e0785fa9f737d287531d06fecb7
parent: 530a2bc5e99ad83c46ce015544cf30173c145bcc
author: cinap_lenrek <[email protected]>
date: Sun Mar 10 20:48:35 EDT 2013
ape/stdio: make fopen() quasi threadsafe for python python uses processes sharing memory. it requires at least fopen() to be called by multiple threads at once so we introduce _IO_newfile() which allocates the FILE structure slot under a lock.
--- a/sys/src/ape/lib/ap/stdio/_IO_getc.c
+++ b/sys/src/ape/lib/ap/stdio/_IO_getc.c
@@ -8,7 +8,7 @@
default: /* CLOSED, WR, ERR, EOF */
return EOF;
case OPEN:
- _IO_setvbuf(f);
+ if(_IO_setvbuf(f)!=0) return EOF;
case RDWR:
case RD:
if(f->flags&STRING) return EOF;
@@ -17,6 +17,7 @@
else
n = f->bufl;
cnt=read(f->fd, f->buf, n);
+ if(f->state==CLOSED) return EOF;
switch(cnt){
case -1: f->state=ERR; return EOF;
case 0: f->state=END; return EOF;
--- /dev/null
+++ b/sys/src/ape/lib/ap/stdio/_IO_newfile.c
@@ -1,0 +1,27 @@
+/*
+ * pANS stdio -- fopen
+ */
+#include "iolib.h"
+
+#define _PLAN9_SOURCE
+#include <lock.h>
+
+FILE *_IO_newfile(void)
+{
+ static FILE *fx=0;
+ static Lock fl;
+ FILE *f;
+ int i;
+
+ lock(&fl);
+ for(i=0; i<FOPEN_MAX; i++){
+ if(fx==0 || ++fx >= &_IO_stream[FOPEN_MAX]) fx=_IO_stream;
+ if(fx->state==CLOSED)
+ break;
+ }
+ f = fx;
+ unlock(&fl);
+ if(f->state!=CLOSED)
+ return NULL;
+ return f;
+}
--- a/sys/src/ape/lib/ap/stdio/_IO_putc.c
+++ b/sys/src/ape/lib/ap/stdio/_IO_putc.c
@@ -19,7 +19,8 @@
case CLOSED:
return EOF;
case OPEN:
- _IO_setvbuf(f);
+ if(_IO_setvbuf(f)!=0)
+ return EOF;
/* fall through */
case RDWR:
case END:
--- a/sys/src/ape/lib/ap/stdio/fclose.c
+++ b/sys/src/ape/lib/ap/stdio/fclose.c
@@ -3,12 +3,28 @@
*/
#include "iolib.h"
int fclose(FILE *f){
- int error=0;
+ int d, error=0;
+ char *p;
+
if(!f) return EOF;
if(f->state==CLOSED) return EOF;
if(fflush(f)==EOF) error=EOF;
- if(f->flags&BALLOC) free(f->buf);
- if(!(f->flags&STRING) && close(f->fd)<0) error=EOF;
+ if(f->flags&BALLOC){
+ if((p = f->buf)!=0){
+ f->buf = 0;
+ f->wp = 0;
+ f->rp = 0;
+ f->lp = 0;
+ free(p);
+ }
+ }
+ if(!(f->flags&STRING)){
+ if((d = f->fd)>=0){
+ f->fd = -1;
+ if(close(d) < 0)
+ error = EOF;
+ }
+ }
f->state=CLOSED;
f->flags=0;
return error;
--- a/sys/src/ape/lib/ap/stdio/fdopen.c
+++ b/sys/src/ape/lib/ap/stdio/fdopen.c
@@ -14,10 +14,8 @@
*/
FILE *fdopen(const int fd, const char *mode){
FILE *f;
- for(f=_IO_stream;f!=&_IO_stream[FOPEN_MAX];f++)
- if(f->state==CLOSED)
- break;
- if(f==&_IO_stream[FOPEN_MAX])
+
+ if((f = _IO_newfile()) == NULL)
return NULL;
f->fd=fd;
if(mode[0]=='a')
--- a/sys/src/ape/lib/ap/stdio/fflush.c
+++ b/sys/src/ape/lib/ap/stdio/fflush.c
@@ -21,7 +21,8 @@
case WR:
cnt=(f->flags&LINEBUF?f->lp:f->wp)-f->buf;
if(cnt && write(f->fd, f->buf, cnt)!=cnt){
- f->state=ERR;
+ if(f->state!=CLOSED)
+ f->state=ERR;
return EOF;
}
f->rp=f->wp=f->buf;
--- a/sys/src/ape/lib/ap/stdio/fopen.c
+++ b/sys/src/ape/lib/ap/stdio/fopen.c
@@ -2,10 +2,11 @@
* pANS stdio -- fopen
*/
#include "iolib.h"
+
FILE *fopen(const char *name, const char *mode){
FILE *f;
- for(f=_IO_stream;f!=&_IO_stream[FOPEN_MAX];f++)
- if(f->state==CLOSED)
- return freopen(name, mode, f);
- return NULL;
+
+ if((f = _IO_newfile()) == NULL)
+ return NULL;
+ return freopen(name, mode, f);
}
--- a/sys/src/ape/lib/ap/stdio/fread.c
+++ b/sys/src/ape/lib/ap/stdio/fread.c
@@ -12,7 +12,7 @@
s=(char *)p;
n=recl*nrec;
- while(n>0){
+ while(n>0 && f->state!=CLOSED){
d=f->wp-f->rp;
if(d>0){
if(d>n)
@@ -23,7 +23,8 @@
if(f->buf==f->unbuf || (n >= BIGN && f->state==RD && !(f->flags&STRING))){
d=read(f->fd, s, n);
if(d<=0){
- f->state=(d==0)?END:ERR;
+ if(f->state!=CLOSED)
+ f->state=(d==0)?END:ERR;
goto ret;
}
}else{
--- a/sys/src/ape/lib/ap/stdio/fwrite.c
+++ b/sys/src/ape/lib/ap/stdio/fwrite.c
@@ -12,7 +12,7 @@
s=(char *)p;
n=recl*nrec;
- while(n>0){
+ while(n>0 && f->state!=CLOSED){
d=f->rp-f->wp;
if(d>0){
if(d>n)
@@ -26,7 +26,8 @@
if(f->flags&APPEND)
lseek(f->fd, 0L, SEEK_END);
if(write(f->fd, f->buf, d)!=d){
- f->state=ERR;
+ if(f->state!=CLOSED)
+ f->state=ERR;
goto ret;
}
f->wp=f->rp=f->buf;
@@ -35,7 +36,8 @@
lseek(f->fd, 0L, SEEK_END);
d=write(f->fd, s, n);
if(d<=0){
- f->state=ERR;
+ if(f->state!=CLOSED)
+ f->state=ERR;
goto ret;
}
} else {
--- a/sys/src/ape/lib/ap/stdio/iolib.h
+++ b/sys/src/ape/lib/ap/stdio/iolib.h
@@ -42,3 +42,4 @@
FILE *_IO_sopenr(const char*);
FILE *_IO_sopenw(void);
char *_IO_sclose(FILE *);
+FILE *_IO_newfile(void);
--- a/sys/src/ape/lib/ap/stdio/mkfile
+++ b/sys/src/ape/lib/ap/stdio/mkfile
@@ -2,6 +2,7 @@
<$APE/config
LIB=/$objtype/lib/ape/libap.a
OFILES=\
+ _IO_newfile.$O\
_IO_getc.$O\
_IO_putc.$O\
_dtoa.$O\
--- a/sys/src/ape/lib/ap/stdio/rdline.c
+++ b/sys/src/ape/lib/ap/stdio/rdline.c
@@ -12,7 +12,8 @@
default: /* CLOSED, WR, ERR, EOF */
return NULL;
case OPEN:
- _IO_setvbuf(f);
+ if(_IO_setvbuf(f)!=0)
+ return NULL;
case RDWR:
f->state=RD;
case RD:
@@ -46,6 +47,8 @@
break;
}
cnt=read(f->fd, f->wp, cnt);
+ if(f->state==CLOSED)
+ return NULL;
if(cnt==-1){
f->state=ERR;
return NULL;
--- a/sys/src/ape/lib/ap/stdio/sopenr.c
+++ b/sys/src/ape/lib/ap/stdio/sopenr.c
@@ -6,8 +6,9 @@
FILE *_IO_sopenr(const char *s){
FILE *f;
- for(f=_IO_stream;f!=&_IO_stream[FOPEN_MAX];f++) if(f->state==CLOSED) break;
- if(f==&_IO_stream[FOPEN_MAX]) return NULL;
+
+ if((f=_IO_newfile())==NULL)
+ return NULL;
f->buf=f->rp=(char *)s; /* what an annoyance const is */
f->bufl=strlen(s);
f->wp=f->buf+f->bufl;
--- a/sys/src/ape/lib/ap/stdio/sopenw.c
+++ b/sys/src/ape/lib/ap/stdio/sopenw.c
@@ -5,8 +5,9 @@
FILE *_IO_sopenw(void){
FILE *f;
- for(f=_IO_stream;f!=&_IO_stream[FOPEN_MAX];f++) if(f->state==CLOSED) break;
- if(f==&_IO_stream[FOPEN_MAX]) return NULL;
+
+ if((f=_IO_newfile())==NULL)
+ return NULL;
f->buf=f->rp=f->wp=0;
f->state=OPEN;
f->flags=STRING;