diff options
author | David Hedbor <neotron@php.net> | 1999-11-25 02:05:35 +0000 |
---|---|---|
committer | David Hedbor <neotron@php.net> | 1999-11-25 02:05:35 +0000 |
commit | 5f5bd0954b79eec449282bd64098e18b3e3681c8 (patch) | |
tree | 12c46db6176e51eb39fdd286880c165acd3e3ec5 | |
parent | 353686c9c594edfdd880cdab25ed4ed2a9eb33b1 (diff) | |
download | php-git-5f5bd0954b79eec449282bd64098e18b3e3681c8.tar.gz |
Implemented direct writing to the client's FD if RXML parsing of the result isn't selected.
-rw-r--r-- | sapi/roxen/README | 18 | ||||
-rw-r--r-- | sapi/roxen/phpmod.pike | 6 | ||||
-rw-r--r-- | sapi/roxen/roxen.c | 122 |
3 files changed, 112 insertions, 34 deletions
diff --git a/sapi/roxen/README b/sapi/roxen/README index 2c46878bbc..b12662f3e3 100644 --- a/sapi/roxen/README +++ b/sapi/roxen/README @@ -1,8 +1,16 @@ -Roxen PHP support. Very early version. Don't expect to be able to get -it to work. Requires a very late Pike 0.7 and Roxen 1.4. Anything else will be -futile, and even that might be. Beware! It is not thread safe yet. As -a matter of fact it doesn't work when threads are enabled when -compiling PHP +Roxen PHP support. Early version. Don't expect to be able to get it to +work. Requires Pike 0.7.79 and Roxen 1.4. Anything less won't work. + +The module is now thread safe, in a couple of different modes. First +mode, the default, uses a process global PHP lock in the Roxen +module. This means that all PHP-requests are serialized (ie only one +script is executed at any one time). The second option is using ZTS +(Zend Thread Safe mode). Unless --enable-roxen-zts is specified, this +won't be used. For now this uses a global lock in the PHP interpreter +so the end result is the same (only one concurrent script). In the +future this might change though, but for now you are better off using +the non-ZendThreadSafe version (which works fine with Roxen and +threads). - The Author, David Hedbor <neotron@php.net> diff --git a/sapi/roxen/phpmod.pike b/sapi/roxen/phpmod.pike index df595b82ef..2769bbd251 100644 --- a/sapi/roxen/phpmod.pike +++ b/sapi/roxen/phpmod.pike @@ -158,6 +158,12 @@ class PHPScript mapping options = ([ "env":environment, ]); +#if 0 + if(!QUERY(rxml)) { + mid->my_fd->set_blocking(); + options->my_fd = mid->my_fd; + } +#endif mid->my_fd->set_close_callback(done); interpretor->run(command, options, this_object(), done); return this_object(); diff --git a/sapi/roxen/roxen.c b/sapi/roxen/roxen.c index 0687871d92..80eed97c7a 100644 --- a/sapi/roxen/roxen.c +++ b/sapi/roxen/roxen.c @@ -63,9 +63,9 @@ typedef struct { struct mapping *request_data; - struct object *my_fd; + struct object *my_fd_obj; + int my_fd; char *filename; - PIKE_MUTEX_T roxen_php_execution_lock; } php_roxen_request; @@ -82,17 +82,29 @@ static int roxen_globals_id; # define GET_THIS() php_roxen_request *_request = ts_resource(roxen_globals_id); # define THIS _request -# define MY_FD ((struct object *)(THIS->my_fd)) -# define REQUEST_DATA ((struct mapping *)(THIS->request_data)) #else static php_roxen_request *current_request = NULL; # define GET_THIS() current_request = ((php_roxen_request *)fp->current_storage) # define THIS current_request -# define MY_FD ((struct object *)(THIS->my_fd)) -# define REQUEST_DATA ((struct mapping *)(THIS->request_data)) #endif +/* File descriptor integer. Used to write directly to the FD without + * passing Pike + */ +#define MY_FD (THIS->my_fd) + +/* FD object. Really a PHPScript object from Pike which implements a couple + * of functions to handle headers, writing and buffering. + */ +#define MY_FD_OBJ ((struct object *)(THIS->my_fd_obj)) + +/* Mapping with data supplied from the calling Roxen module. Contains + * a mapping with headers, an FD object etc. + */ +#define REQUEST_DATA ((struct mapping *)(THIS->request_data)) + + #if defined(_REENTRANT) && !defined(ROXEN_USE_ZTS) /* Lock used to serialize the PHP execution. If ROXEN_USE_ZTS is defined, we * are using the PHP thread safe mechanism instead. @@ -226,9 +238,14 @@ php_roxen_low_ub_write(const char *str, uint str_length) { #ifdef ROXEN_USE_ZTS GET_THIS(); #endif + if(!MY_FD_OBJ->prog) { + PG(connection_status) = PHP_CONNECTION_ABORTED; + zend_bailout(); + return -1; + } to_write = make_shared_binary_string(str, str_length); push_string(to_write); - safe_apply(MY_FD, "write", 1); + safe_apply(MY_FD_OBJ, "write", 1); if(sp[-1].type == PIKE_T_INT) sent_bytes = sp[-1].u.integer; pop_stack(); @@ -249,8 +266,35 @@ php_roxen_low_ub_write(const char *str, uint str_length) { static int php_roxen_sapi_ub_write(const char *str, uint str_length) { - int sent_bytes = 0; - THREAD_SAFE_RUN(sent_bytes = php_roxen_low_ub_write(str, str_length), "write"); + int sent_bytes = 0, fd = MY_FD; + if(fd) + { + for(sent_bytes=0;sent_bytes < str_length;) + { + int written; + written = fd_write(fd, str + sent_bytes, str_length - sent_bytes); + if(written < 0) + { + switch(errno) + { + default: + /* This means the connection is closed. Dead. Gone. *sniff* */ + PG(connection_status) = PHP_CONNECTION_ABORTED; + zend_bailout(); + return sent_bytes; + case EINTR: + case EWOULDBLOCK: + continue; + } + + } else { + sent_bytes += written; + } + } + } else { + THREAD_SAFE_RUN(sent_bytes = php_roxen_low_ub_write(str, str_length), + "write"); + } fprintf(stderr, "write done.\n"); return sent_bytes; } @@ -328,36 +372,33 @@ php_roxen_low_send_headers(sapi_headers_struct *sapi_headers SLS_DC) #ifdef ROXEN_USE_ZTS GET_THIS(); #endif + if(!MY_FD_OBJ->prog) { + PG(connection_status) = PHP_CONNECTION_ABORTED; + zend_bailout(); + return SAPI_HEADER_SEND_FAILED; + } ind = make_shared_string(" _headers"); s_headermap = low_mapping_string_lookup(REQUEST_DATA, ind); free_string(ind); fprintf(stderr, "Send Headers (%d)...\n", SG(sapi_headers).http_response_code); - + push_int(SG(sapi_headers).http_response_code); if(s_headermap && s_headermap->type == PIKE_T_MAPPING) ref_push_mapping(s_headermap->u.mapping); else push_int(0); - fprintf(stderr, "Send Headers 1 (%d)...\n", SG(sapi_headers).http_response_code); - safe_apply(MY_FD, "send_headers", 2); - fprintf(stderr, "Send Headers 1 (%d)...\n", SG(sapi_headers).http_response_code); + safe_apply(MY_FD_OBJ, "send_headers", 2); pop_stack(); - fprintf(stderr, "Send Headers 2 (%d)...\n", SG(sapi_headers).http_response_code); - /* - if(SG(sapi_headers).send_default_content_type) { - Ns_ConnSetRequiredHeaders(NSG(conn), "text/html", 0); - } - Ns_ConnFlushHeaders(NSG(conn), SG(sapi_headers).http_response_code); - */ return SAPI_HEADER_SENT_SUCCESSFULLY; } static int php_roxen_sapi_send_headers(sapi_headers_struct *sapi_headers SLS_DC) { - THREAD_SAFE_RUN(php_roxen_low_send_headers(sapi_headers SLS_CC), "send headers"); - return SAPI_HEADER_SENT_SUCCESSFULLY; + int res = 0; + THREAD_SAFE_RUN(res = php_roxen_low_send_headers(sapi_headers SLS_CC), "send headers"); + return res; } /* @@ -373,8 +414,14 @@ INLINE static int php_roxen_low_read_post(char *buf, uint count_bytes) #endif fprintf(stderr, "read post (%d bytes max)\n", count_bytes); + if(!MY_FD_OBJ->prog) { + PG(connection_status) = PHP_CONNECTION_ABORTED; + zend_bailout(); + return -1; + } + push_int(count_bytes); - safe_apply(MY_FD, "read_post", 1); + safe_apply(MY_FD_OBJ, "read_post", 1); if(sp[-1].type == T_STRING) { MEMCPY(buf, sp[-1].u.string->str, total_read = sp[-1].u.string->len); buf[total_read] = '\0'; @@ -581,25 +628,30 @@ static int php_roxen_module_main(SLS_D) void f_php_roxen_request_handler(INT32 args) { - struct object *my_fd; + struct object *my_fd_obj; struct mapping *request_data; - struct svalue *done_callback; - struct pike_string *script; + struct svalue *done_callback, *raw_fd; + struct pike_string *script, *ind; int status = 1; SLS_FETCH(); +#ifdef ROXEN_USE_ZTS GET_THIS(); +#endif if(current_thread == th_self()) error("PHP4.Interpetor->run: Tried to run a PHP-script from a PHP " "callback!"); get_all_args("PHP4.Interpretor->run", args, "%S%m%O%*", &script, - &request_data, &my_fd, &done_callback); + &request_data, &my_fd_obj, &done_callback); if(done_callback->type != PIKE_T_FUNCTION) error("PHP4.Interpretor->run: Bad argument 4, expected function.\n"); PHP_LOCK(THIS); /* Need to lock here or reusing the same object might cause * problems in changing stuff in that object */ +#ifndef ROXEN_USE_ZTS + GET_THIS(); +#endif THIS->request_data = request_data; - THIS->my_fd = my_fd; + THIS->my_fd_obj = my_fd_obj; THIS->filename = script->str; current_thread = th_self(); SG(request_info).query_string = lookup_string_header("QUERY_STRING", 0);; @@ -615,6 +667,18 @@ void f_php_roxen_request_handler(INT32 args) SG(request_info).content_type = "text/html"; SG(request_info).auth_user = NULL; SG(request_info).auth_password = NULL; + + ind = make_shared_binary_string("my_fd", 5); + raw_fd = low_mapping_string_lookup(THIS->request_data, ind); + if(raw_fd && raw_fd->type == PIKE_T_OBJECT) + { + int fd = fd_from_object(raw_fd->u.object); + if(fd == -1) + error("PHP4.Interpretor->run: my_fd object not open or not an FD.\n"); + THIS->my_fd = fd; + } else + THIS->my_fd = 0; + status = php_roxen_module_main(SLS_C); current_thread = -1; PHP_UNLOCK(THIS); @@ -650,7 +714,7 @@ void pike_module_init() #endif #endif sapi_startup(&sapi_module); - sapi_module.startup(&sapi_module); + php_roxen_startup(&sapi_module); roxen_php_initialized = 1; PHP_INIT_LOCK(); } |