fix iob_write to handle failure properly

document that the iob_write callback should limit itself
master
leitner 20 years ago
parent f8d16ad407
commit bbf4c614bf

@ -4,6 +4,8 @@
#include <unistd.h> in io/io_sendfile.c (broken OpenBSD, thx Rob) #include <unistd.h> in io/io_sendfile.c (broken OpenBSD, thx Rob)
add scan_urlencoded2 (like scan_urlencoded but will not convert '+' to add scan_urlencoded2 (like scan_urlencoded but will not convert '+' to
' '; needed for web servers, so they can serve libstdc++.tar.gz) ' '; needed for web servers, so they can serve libstdc++.tar.gz)
fix iob_write to handle failure properly
document that the iob_write callback should limit itself
0.21: 0.21:
errno cleanup and man page updates (Rolf Eike Beer) errno cleanup and man page updates (Rolf Eike Beer)

@ -25,5 +25,13 @@ writable, and then calling iob_write until it returns 0, -1 or -3.
If it returns 0, terminate the loop (everything was written OK). If it If it returns 0, terminate the loop (everything was written OK). If it
returns -1, call io_wait again. If it returned -3, signal an error. returns -1, call io_wait again. If it returned -3, signal an error.
.SH NOTE
iob_write will continue to call your callback until it returns an error.
So if you are in a state machine, for example a web server using this
for SSL support, make sure to write at most n bytes at a time (e.g. 64k)
and the next time you are called return -1. Otherwise iob_write might
not return until the whole file is served.
.SH "SEE ALSO" .SH "SEE ALSO"
iob_send(3) iob_send(3)

@ -18,16 +18,14 @@ int64 iob_write(int64 s,io_batch* b,io_write_callback cb) {
sent=io_mmapwritefile(s,e[i].fd,e[i].offset,e[i].n,cb); sent=io_mmapwritefile(s,e[i].fd,e[i].offset,e[i].n,cb);
else else
sent=cb(s,e[i].buf+e[i].offset,e[i].n); sent=cb(s,e[i].buf+e[i].offset,e[i].n);
if (sent > e[i].n) sent=e[i].n; /* can't happen */ if (sent>0 && sent>e[i].n) sent=e[i].n; /* can't happen */
thatsit=(sent != e[i].n); thatsit=(sent != e[i].n);
if (sent==-1 && errno!=EAGAIN) if (sent<=0)
sent=-3; return total?total:sent;
if (sent>0) {
e[i].offset+=sent; e[i].offset+=sent;
e[i].n-=sent; e[i].n-=sent;
total+=sent; total+=sent;
} else b->bytesleft-=sent;
return total?total:sent;
if (thatsit) break; if (thatsit) break;
} }
if (total == b->bytesleft) if (total == b->bytesleft)

23
t.c

@ -19,22 +19,43 @@
#include <errno.h> #include <errno.h>
#include <string.h> #include <string.h>
#include <assert.h> #include <assert.h>
#include <errmsg.h> #include "errmsg.h"
#include "iob.h"
#define rdtscl(low) \ #define rdtscl(low) \
__asm__ __volatile__ ("rdtsc" : "=a" (low) : : "edx") __asm__ __volatile__ ("rdtsc" : "=a" (low) : : "edx")
int64 writecb(int64 fd,const void* buf,uint64 n) {
#if 0
int r;
int todo=n>=65536?65536:n;
r=write(fd,buf,todo);
if (r==-1 && r!=EAGAIN) r=-3;
return r;
#endif
return -1;
}
int main(int argc,char* argv[]) { int main(int argc,char* argv[]) {
static io_batch b;
int64 fd=open("t.c",0);
iob_addbuf(&b,"fnord",5);
iob_addfile_close(&b,fd,0,7365);
iob_write(1,&b,writecb);
#if 0
char dest[1024]; char dest[1024];
unsigned long len; unsigned long len;
scan_urlencoded2("libstdc++.tar.gz",dest,&len); scan_urlencoded2("libstdc++.tar.gz",dest,&len);
buffer_putmflush(buffer_1,dest,"\n"); buffer_putmflush(buffer_1,dest,"\n");
#endif
#if 0 #if 0
static stralloc sa; static stralloc sa;
stralloc_copym(&sa,"foo ","bar ","baz.\n"); stralloc_copym(&sa,"foo ","bar ","baz.\n");
write(1,sa.s,sa.len); write(1,sa.s,sa.len);
#endif #endif
#if 0
buffer_putmflush(buffer_1,"foo ","bar ","baz.\n"); buffer_putmflush(buffer_1,"foo ","bar ","baz.\n");
#endif
#if 0 #if 0
char* c="fnord"; char* c="fnord";
int fd=open_read(c); int fd=open_read(c);

Loading…
Cancel
Save