From ea496f16ae4ae973b9a927f662cd82b1e611ae61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Grubbstr=C3=B6m=20=28Grubba=29?= <grubba@grubba.org> Date: Wed, 14 Apr 1999 23:43:01 +0200 Subject: [PATCH] Fixed some bugs. Rev: src/modules/files/sendfile.c:1.2 --- src/modules/files/sendfile.c | 252 +++++++++++++++++++++++------------ 1 file changed, 166 insertions(+), 86 deletions(-) diff --git a/src/modules/files/sendfile.c b/src/modules/files/sendfile.c index e2b5a095a4..8e0fc495ae 100644 --- a/src/modules/files/sendfile.c +++ b/src/modules/files/sendfile.c @@ -1,5 +1,5 @@ /* - * $Id: sendfile.c,v 1.1 1999/04/03 01:54:04 grubba Exp $ + * $Id: sendfile.c,v 1.2 1999/04/14 21:43:01 grubba Exp $ * * Sends headers + from_fd[off..off+len-1] + trailers to to_fd asyncronously. * @@ -39,6 +39,27 @@ #define SF_DFPRINTF(X) #endif /* SF_DEBUG */ +#define BUF_SIZE 65536 + + +/* + * Only support for threaded operation right now. + */ +#ifdef _REENTRANT + + +/* + * Struct's + */ + +#ifndef HAVE_STRUCT_IOVEC +struct iovec { + void *iov_base; + int iov_len; +}; +#endif /* !HAVE_STRUCT_IOVEC */ + + struct pike_sendfile { struct object *self; @@ -67,10 +88,15 @@ struct pike_sendfile int tr_cnt; struct iovec *iovs; + char *buffer; }; #define THIS ((struct pike_sendfile *)(fp->current_storage)) +/* + * Globals + */ + static struct program *pike_sendfile_prog = NULL; /* @@ -89,6 +115,9 @@ static void exit_pike_sendfile(struct object *o) if (THIS->iovs) { free(THIS->iovs); } + if (THIS->buffer) { + free(THIS->buffer); + } if (THIS->headers) { free_array(THIS->headers); } @@ -112,43 +141,73 @@ static void exit_pike_sendfile(struct object *o) free_svalue(&(THIS->callback)); } -#ifdef _REENTRANT - /* - * Code called in the threaded case. + * Fallback code */ -void call_callback_and_free(struct callback *cb, void *this_, void *arg) +#ifndef HAVE_WRITEV +#define writev my_writev +static int writev(int fd, struct iovec *iov, int n) { - struct pike_sendfile *this = this_; - int sz; - - SF_DFPRINTF((stderr, "sendfile: Calling callback...\n")); + if (n) { + return write(fd, iov->iov_data, iov->iov_len); + } + return 0; +} +#endif /* !HAVE_WRITEV */ - remove_callback(cb); +/* + * Helper functions + */ - /* Make sure we get freed in case of error */ - push_object(this->self); - this->self = NULL; +void sf_call_callback(struct pike_sendfile *this) +{ + if (this->callback.type != T_INT) { + int sz = this->args->size; - push_int(this->sent); - sz = this->args->size; - push_array_items(this->args); - this->args = NULL; + push_int(this->sent); + push_array_items(this->args); + this->args = NULL; - if (this->callback.type != T_INT) { apply_svalue(&this->callback, 1 + sz); pop_stack(); free_svalue(&this->callback); this->callback.type = T_INT; this->callback.u.integer = 0; + } else { + free_array(this->args); + this->args = NULL; + } +} + +void call_callback_and_free(struct callback *cb, void *this_, void *arg) +{ + struct pike_sendfile *this = this_; + int sz; + + SF_DFPRINTF((stderr, "sendfile: Calling callback...\n")); + + remove_callback(cb); + +#ifdef _REENTRANT + if (this->self) { + /* Make sure we get freed in case of error */ + push_object(this->self); + this->self = NULL; } +#endif /* _REENTRANT */ + + sf_call_callback(this); /* Free ourselves */ pop_stack(); } +/* + * Code called in the threaded case. + */ + /* writev() without the IOV_MAX limit. */ int send_iov(int fd, struct iovec *iov, int iovcnt) { @@ -279,46 +338,39 @@ void *worker(void *this_) #endif /* HAVE_SENDFILE && !HAVE_FREEBSD_SENDFILE */ SF_DFPRINTF((stderr, "sendfile: Sending file by hand\n")); + lseek(this->from_fd, this->offset, SEEK_SET); { -#define BUF_SIZE 65536 - char *buffer = malloc(BUF_SIZE); int buflen; - - lseek(this->from_fd, this->offset, SEEK_SET); - - if (buffer) { - int len = this->len; - if (len > BUF_SIZE) { - len = BUF_SIZE; - } - while ((buflen = read(this->from_fd, buffer, len)) > 0) { - char *buf = buffer; - this->len -= buflen; - this->offset += buflen; - while (buflen) { - int wrlen = write(this->to_fd, buf, buflen); - if ((wrlen < 0) && (errno == EINTR)) { - continue; - } else if (wrlen <= 0) { - free(buffer); - goto send_trailers; - } - buf += wrlen; - buflen -= wrlen; - this->sent += wrlen; - } - len = this->len; - if (len > BUF_SIZE) { - len = BUF_SIZE; + int len = this->len; + if ((len > BUF_SIZE) || (len < 0)) { + len = BUF_SIZE; + } + while ((buflen = read(this->from_fd, this->buffer, len)) > 0) { + char *buf = this->buffer; + this->len -= buflen; + this->offset += buflen; + while (buflen) { + int wrlen = write(this->to_fd, buf, buflen); + if ((wrlen < 0) && (errno == EINTR)) { + continue; + } else if (wrlen <= 0) { + goto send_trailers; } + buf += wrlen; + buflen -= wrlen; + this->sent += wrlen; + } + len = this->len; + if ((len > BUF_SIZE) || (len < 0)) { + len = BUF_SIZE; } - free(buffer); -#undef BUF_SIZE - } else { - /* FIXME: Out of memory. */ } } send_trailers: + /* No more need for the buffer */ + free(this->buffer); + this->buffer = NULL; + SF_DFPRINTF((stderr, "sendfile: Sending trailers.\n")); if (this->tr_cnt) { @@ -381,10 +433,8 @@ void *worker(void *this_) return NULL; } -#endif /* _REENTRANT */ - /* - * Callable functions + * Functions callable from Pike code */ /* void create(array(string) headers, object from, int offset, int len, @@ -445,34 +495,43 @@ static void sf_create(INT32 args) /* Note: No need for safe_apply() */ sf.from_fd = -1; if (sf.from_file) { - apply(sf.from_file, "query_fd", 0); - if (sp[-1].type != T_INT) { + if (sf.len) { + apply(sf.from_file, "query_fd", 0); + if (sp[-1].type != T_INT) { + pop_stack(); + bad_arg_error("sendfile", sp-args, args, 2, "object", sp+1-args, + "Bad argument 2 to sendfile(): " + "query_fd() returned non-integer.\n"); + } + sf.from_fd = sp[-1].u.integer; pop_stack(); - bad_arg_error("sendfile", sp-args, args, 2, "object", sp+1-args, - "Bad argument 2 to sendfile(): " - "query_fd() returned non-integer.\n"); - } - sf.from_fd = sp[-1].u.integer; - pop_stack(); - /* Fix offset */ - if (sf.offset < 0) { - if (sf.from_fd >= 0) { - sf.offset = tell(sf.from_fd); - } else { - apply(sf.from_file, "tell", 0); - if (sp[-1].type != T_INT) { + /* Fix offset */ + if (sf.offset < 0) { + if (sf.from_fd >= 0) { + sf.offset = tell(sf.from_fd); + } else { + apply(sf.from_file, "tell", 0); + if (sp[-1].type != T_INT) { + pop_stack(); + bad_arg_error("sendfile", sp-args, args, 2, "object", sp+1-args, + "Bad argument 2 to sendfile(): " + "tell() returned non-integer.\n"); + } + sf.offset = sp[-1].u.integer; pop_stack(); - bad_arg_error("sendfile", sp-args, args, 2, "object", sp+1-args, - "Bad argument 2 to sendfile(): " - "tell() returned non-integer.\n"); } - sf.offset = sp[-1].u.integer; - pop_stack(); } - } - if (sf.offset < 0) { - sf.offset = 0; + if (sf.offset < 0) { + sf.offset = 0; + } + } else { + /* No need for the from_file object. */ + /* NOTE: We need to zap from_file from the stack too. */ + free_object(sf.from_file); + sf.from_file = NULL; + sp[1-args].type = T_INT; + sp[1-args].u.integer = 0; } } apply(sf.to_file, "query_fd", 0); @@ -535,10 +594,10 @@ static void sf_create(INT32 args) sf.trailers = a; } - /* Note: we hold a reference to ourselves. - * The gc() won't find it, so be carefull. - */ - add_ref(sf.self = fp->current_object); + if (sf.from_file) { + /* We may need a buffer to hold the data */ + sf.buffer = (char *)xalloc(BUF_SIZE); + } /* * Setup done. Note that we keep refs to all refcounted svalues in @@ -548,25 +607,43 @@ static void sf_create(INT32 args) *THIS = sf; args = 0; -#ifdef _REENTRANT if (((sf.from_fd >= 0) || (!sf.from_file)) && (sf.to_fd >= 0)) { + /* Threaded blocking mode possible */ THREAD_T th_id; + + /* Make sure both file objects are in blocking mode. + */ + if (THIS->from_file) { + apply(THIS->from_file, "set_blocking", 0); + pop_stack(); + } + apply(THIS->to_file, "set_blocking", 0); + pop_stack(); + + /* Note: we hold a reference to ourselves. + * The gc() won't find it, so be carefull. + */ + add_ref(THIS->self = fp->current_object); + /* The worker will have a ref. */ th_create_small(&th_id, worker, THIS); } else { -#endif /* _REENTRANT */ - /* Not implemented yet */ - free_object(THIS->self); - THIS->self = NULL; + /* Nonblocking operation needed */ + + /* Not supported */ + error("Unsupported operation\n"); } return; } +#endif /* _REENTRANT */ + /* * Module init code */ void pike_module_init(void) { +#ifdef _REENTRANT start_new_program(); ADD_STORAGE(struct pike_sendfile); map_variable("_args", "array(mixed)", 0, OFFSETOF(pike_sendfile, args), @@ -584,12 +661,15 @@ void pike_module_init(void) pike_sendfile_prog = end_program(); add_program_constant("sendfile", pike_sendfile_prog, 0); +#endif /* _REENTRANT */ } void pike_module_exit(void) { +#ifdef _REENTRANT if (pike_sendfile_prog) { free_program(pike_sendfile_prog); pike_sendfile_prog = NULL; } +#endif /* _REENTRANT */ } -- GitLab