Finally, there is a user notice this problem :) It's supposed to be fixed by my patch, but I'm holding commit. I appreciate if you could help to test the patch.
1) Download latest snapshot http://snaps.php.net/ 2) Apply attached patch. patch -p0 < session.diff in php source root. -- Yasuo Ohgaki Rick Morris wrote: > I have tried mm as a session handler three times, on three different Linux > boxes. Each one was a server under heavy load, running many concurrent > sessions, so I was hoping mm would solve some performance issues, but have > been disappointed each time. > > So far, I am 0 for 3 on this, having done _everything_ by the book. I am > running completely standard stuff: Apache (latest source), MySQL, PHP 4.0.6, > or PHP 4.1.1. On two mature kernels ( 2.2.19, and 2.4.17), using either the > RPM for mm, or compiling from source, I have come up against the same wall: > > Every time I try one of these heavy-load systems with the mm session > handler, performance gets WORSE instead of better. On the latest system > (Dual 1.1 GHz, 2 GB RAM, 4-disk RAID 0+1), I was losing sessions left and > right. The system could only handle about 100-150 concurrent users before > session keys started disappearing, and users would get logged out, On kernel > 2.2.19, over a period of minutes, performance would deteriorate until I > started getting segfaults. On each system, when I went back to "files" as a > session handler, the problem went away. > > So, is there something I am doing wrong? Is there some trick to configuring > mm and PHP, that is not documented, or is there a problem with Linux and mm > itself? Has anyone here successfully used mm as a session handler? On a > high-performance system? > > Any ideas, or should I submit this as a bug? If so, is it a bug with Linux, > with the MM library, or with PHP? > > Thanks, > > Rick Morris > >
? ext/session/tmp.diff ? ext/session/bak Index: ext/session//mod_files.c =================================================================== RCS file: /repository/php4/ext/session/mod_files.c,v retrieving revision 1.67 diff -u -r1.67 mod_files.c --- ext/session//mod_files.c 3 Feb 2002 05:40:19 -0000 1.67 +++ ext/session//mod_files.c 5 Feb 2002 03:24:15 -0000 @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: mod_files.c,v 1.67 2002/02/03 05:40:19 yohgaki Exp $ */ +/* $Id: mod_files.c,v 1.66 2002/02/03 03:17:35 yohgaki Exp $ */ #include "php.h" @@ -123,7 +123,7 @@ } } -static void ps_files_open(ps_files *data, const char *key) +static int ps_files_open(ps_files *data, const char *key) { char buf[MAXPATHLEN]; TSRMLS_FETCH(); @@ -138,7 +138,7 @@ if (!ps_files_valid_key(key) || !ps_files_path_create(buf, sizeof(buf), data, key)) - return; + return FAILURE; data->lastkey = estrdup(key); @@ -153,10 +153,13 @@ if (data->fd != -1) flock(data->fd, LOCK_EX); - if (data->fd == -1) + if (data->fd == -1) { php_error(E_WARNING, "open(%s, O_RDWR) failed: %s (%d)", buf, strerror(errno), errno); + return FAILURE; + } } + return SUCCESS; } static int ps_files_cleanup_dir(const char *dirname, int maxlifetime) @@ -254,7 +257,9 @@ struct stat sbuf; PS_FILES_DATA; - ps_files_open(data, key); + if (ps_files_open(data, key) == FAILURE) + return FAILURE; + if (data->fd < 0) return FAILURE; @@ -283,7 +288,9 @@ long n; PS_FILES_DATA; - ps_files_open(data, key); + if (ps_files_open(data, key) == FAILURE) + return FAILURE; + if (data->fd < 0) return FAILURE; Index: ext/session//mod_mm.c =================================================================== RCS file: /repository/php4/ext/session/mod_mm.c,v retrieving revision 1.31 diff -u -r1.31 mod_mm.c --- ext/session//mod_mm.c 25 Jan 2002 20:59:24 -0000 1.31 +++ ext/session//mod_mm.c 5 Feb 2002 03:24:15 -0000 @@ -319,7 +319,6 @@ { PS_MM_DATA; ps_sd *sd; - int ret = FAILURE; mm_lock(data->mm, MM_LOCK_RD); @@ -329,12 +328,14 @@ *val = emalloc(sd->datalen + 1); memcpy(*val, sd->data, sd->datalen); (*val)[sd->datalen] = '\0'; - ret = SUCCESS; } - + else { + *val = estrdup("\0"); + } + mm_unlock(data->mm); - return ret; + return SUCCESS; } PS_WRITE_FUNC(mm) Index: ext/session//php_session.h =================================================================== RCS file: /repository/php4/ext/session/php_session.h,v retrieving revision 1.68 diff -u -r1.68 php_session.h --- ext/session//php_session.h 5 Feb 2002 01:28:55 -0000 1.68 +++ ext/session//php_session.h 5 Feb 2002 03:24:15 -0000 @@ -61,11 +61,16 @@ #x, ps_open_##x, ps_close_##x, ps_read_##x, ps_write_##x, \ ps_delete_##x, ps_gc_##x -typedef enum { - php_session_disabled, - php_session_none, - php_session_active -} php_session_status; +/* typedef enum { */ +/* php_session_disabled, */ +/* php_session_none, */ +/* php_session_active */ +/* } php_session_status; */ + +#define PS_DISABLED 1 +#define PS_NONE 2 +#define PS_ACTIVE 4 +#define PS_ERROR 8 typedef struct _php_ps_globals { char *save_path; @@ -79,10 +84,11 @@ char *cookie_path; char *cookie_domain; zend_bool cookie_secure; + long rinit_mod; ps_module *mod; void *mod_data; HashTable vars; - php_session_status session_status; + long session_status; long gc_probability; long gc_maxlifetime; int module_number; Index: ext/session//session.c =================================================================== RCS file: /repository/php4/ext/session/session.c,v retrieving revision 1.275 diff -u -r1.275 session.c --- ext/session//session.c 5 Feb 2002 01:30:22 -0000 1.275 +++ ext/session//session.c 5 Feb 2002 03:24:16 -0000 @@ -87,7 +87,7 @@ static void php_session_output_handler(char *output, uint output_len, char **handled_output, uint *handled_output_len, int mode TSRMLS_DC) { - if ((PS(session_status) == php_session_active)) { + if ((PS(session_status) & PS_ACTIVE)) { *handled_output = url_adapt_ext_ex(output, output_len, PS(session_name), PS(id), handled_output_len, (zend_bool) (mode&PHP_OUTPUT_HANDLER_END ? 1 : 0) TSRMLS_CC); } else { *handled_output = NULL; @@ -128,9 +128,12 @@ static PHP_INI_MH(OnUpdateSerializer) { PS(serializer) = _php_find_ps_serializer(new_value TSRMLS_CC); - if(!PS(serializer)) { - php_error(E_ERROR,"Cannot find serialization handler %s",new_value); - } +/* Following lines are commented out to prevent bogus error message at + start up. i.e. Serializer modules are not initilzied before Session + module. */ +/* if(!PS(serializer)) { */ +/* php_error(E_ERROR,"Cannot find serialization handler %s",new_value); */ +/* } */ return SUCCESS; } @@ -477,18 +480,23 @@ { char *ret = NULL; - if (PS(serializer)->encode(&ret, newlen TSRMLS_CC) == FAILURE) + if (PS(serializer)->encode(&ret, newlen TSRMLS_CC) == FAILURE) { + PS(session_status) = PS_ERROR; ret = NULL; - + } + return ret; } static void php_session_decode(const char *val, int vallen TSRMLS_DC) { - php_session_track_init(TSRMLS_C); - if (PS(serializer)->decode(val, vallen TSRMLS_CC) == FAILURE) { - php_session_destroy(TSRMLS_C); - php_error(E_WARNING, "Failed to decode session object. Session has been destroyed."); + if (PS(session_status) & PS_ACTIVE) { + php_session_track_init(TSRMLS_C); + if (PS(serializer)->decode(val, vallen TSRMLS_CC) == FAILURE) { + PS(session_status) = PS_ERROR; + php_session_destroy(TSRMLS_C); + php_error(E_WARNING, "Failed to decode session object. Session +has been destroyed."); + } } } @@ -549,13 +557,17 @@ int vallen; if (PS(mod)->open(&PS(mod_data), PS(save_path), PS(session_name)) == FAILURE) { - php_error(E_ERROR, "Failed to initialize session module"); + PS(session_status) = PS_ERROR; + php_error(E_WARNING, "Failed to initialize session module"); return; } - if (PS(mod)->read(&PS(mod_data), PS(id), &val, &vallen) == SUCCESS) { - php_session_decode(val, vallen TSRMLS_CC); - efree(val); + if (PS(mod)->read(&PS(mod_data), PS(id), &val, &vallen) == FAILURE) { + PS(session_status) = PS_ERROR; + php_error(E_WARNING, "Failed to read session data"); + return; } + php_session_decode(val, vallen TSRMLS_CC); + efree(val); } @@ -569,16 +581,14 @@ ulong num_key; HashPosition pos; - if (!PG(register_globals) && !PS(http_session_vars)) { + if ((!PG(register_globals) && !PS(http_session_vars)) || (PS(session_status) & +(PS_DISABLED|PS_NONE|PS_ERROR))) { return; } - if (PS(http_session_vars)) { - for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(PS(http_session_vars)), &pos); - zend_hash_get_current_key_ex(Z_ARRVAL_P(PS(http_session_vars)), &variable, &variable_len, &num_key, 0, &pos) == HASH_KEY_IS_STRING; - zend_hash_move_forward_ex(Z_ARRVAL_P(PS(http_session_vars)),&pos)) { - PS_ADD_VARL(variable,variable_len-1); - } + for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(PS(http_session_vars)), +&pos); + zend_hash_get_current_key_ex(Z_ARRVAL_P(PS(http_session_vars)), +&variable, &variable_len, &num_key, 0, &pos) == HASH_KEY_IS_STRING; + zend_hash_move_forward_ex(Z_ARRVAL_P(PS(http_session_vars)),&pos)) { + PS_ADD_VARL(variable,variable_len-1); } if (PS(mod_data)) { @@ -591,13 +601,14 @@ } } - if (ret == FAILURE) + if (ret == FAILURE) { + PS(session_status) = PS_ERROR; php_error(E_WARNING, "Failed to write session data (%s). Please " - "verify that the current setting of session.save_path " - "is correct (%s)", - PS(mod)->name, - PS(save_path)); - + "verify that the current setting of +session.save_path " + "is correct (%s)", + PS(mod)->name, + PS(save_path)); + } if (PS(mod_data)) PS(mod)->close(&PS(mod_data)); @@ -744,6 +755,7 @@ smart_str ncookie = {0}; char *date_fmt = NULL; + if (SG(headers_sent)) { char *output_start_filename = php_get_output_start_filename(TSRMLS_C); int output_start_lineno = php_get_output_start_lineno(TSRMLS_C); @@ -834,10 +846,11 @@ int module_number = PS(module_number); int nrand; int lensess; + smart_str var = {0}; PS(apply_trans_sid) = PS(use_trans_sid); - if (PS(session_status) != php_session_none) + if (PS(session_status) & (PS_ACTIVE|PS_ERROR)) return; lensess = strlen(PS(session_name)); @@ -927,30 +940,23 @@ php_session_send_cookie(TSRMLS_C); } - - if (PS(apply_trans_sid)) { - smart_str var = {0}; - - smart_str_appends(&var, PS(session_name)); - smart_str_appendc(&var, '='); - smart_str_appends(&var, PS(id)); - smart_str_0(&var); - REGISTER_STRING_CONSTANT("SID", var.c, 0); - } else { - REGISTER_STRING_CONSTANT("SID", empty_string, 0); - } - - PS(session_status) = php_session_active; + smart_str_appends(&var, PS(session_name)); + smart_str_appendc(&var, '='); + smart_str_appends(&var, PS(id)); + smart_str_0(&var); + REGISTER_STRING_CONSTANT("SID", var.c, 0); if (PS(apply_trans_sid)) { php_session_start_output_handler(4096 TSRMLS_CC); } + PS(session_status) = PS_ACTIVE; + php_session_cache_limiter(TSRMLS_C); php_session_initialize(TSRMLS_C); - if (PS(mod_data) && PS(gc_probability) > 0) { + if ((PS(session_status) & PS_ACTIVE) && PS(gc_probability) > 0) { int nrdels = -1; - + nrand = (int) (100.0*php_combined_lcg(TSRMLS_C)); if (nrand < PS(gc_probability)) { PS(mod)->gc(&PS(mod_data), PS(gc_maxlifetime), &nrdels); @@ -962,18 +968,20 @@ } } + static zend_bool php_session_destroy(TSRMLS_D) { zend_bool retval = SUCCESS; - if (PS(session_status) != php_session_active) { - php_error(E_WARNING, "Trying to destroy uninitialized session"); + if (PS(session_status) & (PS_DISABLED|PS_NONE|PS_ERROR)) { + php_error(E_NOTICE, "Trying to destroy uninitialized session"); return FAILURE; } if (PS(mod)->destroy(&PS(mod_data), PS(id)) == FAILURE) { + PS(session_status) = PS_ERROR; retval = FAILURE; - php_error(E_WARNING, "Session object destruction failed"); + php_error(E_NOTICE, "Session object destruction failed"); } php_rshutdown_session_globals(TSRMLS_C); @@ -1000,9 +1008,15 @@ PS(cookie_lifetime) = Z_LVAL_PP(lifetime); if (ZEND_NUM_ARGS() > 1) { + if (PS(session_status) & (PS_ACTIVE)) { + php_error(E_NOTICE, "%s() cannot set cookie parameter once +session is started.", + get_active_function_name(TSRMLS_C)); + RETURN_FALSE; + } + convert_to_string_ex(path); zend_alter_ini_entry("session.cookie_path", sizeof("session.cookie_path"), Z_STRVAL_PP(path), Z_STRLEN_PP(path), PHP_INI_USER, PHP_INI_STAGE_RUNTIME); - + if (ZEND_NUM_ARGS() > 2) { convert_to_string_ex(domain); zend_alter_ini_entry("session.cookie_domain", sizeof("session.cookie_domain"), Z_STRVAL_PP(domain), Z_STRLEN_PP(domain), PHP_INI_USER, PHP_INI_STAGE_RUNTIME); @@ -1012,6 +1026,7 @@ } } } + } /* }}} */ @@ -1049,6 +1064,12 @@ WRONG_PARAM_COUNT; if (ac == 1) { + if (PS(session_status) & PS_ACTIVE) { + efree(old); + php_error(E_NOTICE, "%s() cannot set session name once session +is started.", + get_active_function_name(TSRMLS_C)); + RETURN_FALSE; + } convert_to_string_ex(p_name); zend_alter_ini_entry("session.name", sizeof("session.name"), Z_STRVAL_PP(p_name), Z_STRLEN_PP(p_name), PHP_INI_USER, PHP_INI_STAGE_RUNTIME); } @@ -1073,19 +1094,28 @@ if (ac == 1) { ps_module *tempmod; + if (PS(session_status) & (PS_ACTIVE|PS_ERROR)) { + efree(old); + php_error(E_NOTICE, "%s() cannot set session module name once +session is started. " + "Current session save handler (%s)", + get_active_function_name(TSRMLS_C), + (PS(mod)->name ? PS(mod)->name : "none")); + RETURN_FALSE; + } + convert_to_string_ex(p_name); tempmod = _php_find_ps_module(Z_STRVAL_PP(p_name) TSRMLS_CC); - if (tempmod) { - if (PS(mod_data)) - PS(mod)->close(&PS(mod_data)); - PS(mod) = tempmod; - PS(mod_data) = NULL; - } else { + if (!tempmod) { efree(old); - php_error(E_ERROR, "Cannot find named PHP session module (%s)", - Z_STRVAL_PP(p_name)); + php_error(E_NOTICE, "Cannot find named PHP session module +(%s)", + Z_STRVAL_PP(p_name)); RETURN_FALSE; } + if (PS(mod_data)) + PS(mod)->close(&PS(mod_data)); + PS(mod) = tempmod; + PS(mod_data) = NULL; + PS(rinit_mod) = 1; } RETVAL_STRING(old, 0); @@ -1103,8 +1133,13 @@ if (ZEND_NUM_ARGS() != 6 || zend_get_parameters_array_ex(6, args) == FAILURE) WRONG_PARAM_COUNT; - if (PS(session_status) != php_session_none) + if (PS(session_status) & PS_ACTIVE) { + php_error(E_NOTICE, "%s() cannot set session save handler functions +once session is started. " + "Current session save handler (%s)", + get_active_function_name(TSRMLS_C), + (PS(mod)->name ? PS(mod)->name : "none")); RETURN_FALSE; + } zend_alter_ini_entry("session.save_handler", sizeof("session.save_handler"), "user", sizeof("user")-1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME); @@ -1133,8 +1168,14 @@ if (ac < 0 || ac > 1 || zend_get_parameters_ex(ac, &p_name) == FAILURE) WRONG_PARAM_COUNT; - + if (ac == 1) { + if (PS(session_status) & PS_ACTIVE) { + efree(old); + php_error(E_NOTICE, "%s() cannot change session save path +once session is started.", + get_active_function_name(TSRMLS_C)); + RETURN_FALSE; + } convert_to_string_ex(p_name); zend_alter_ini_entry("session.save_path", sizeof("session.save_path"), Z_STRVAL_PP(p_name), Z_STRLEN_PP(p_name), PHP_INI_USER, PHP_INI_STAGE_RUNTIME); } @@ -1156,10 +1197,16 @@ if (ac < 0 || ac > 1 || zend_get_parameters_ex(ac, &p_name) == FAILURE) WRONG_PARAM_COUNT; - + if (ac == 1) { - convert_to_string_ex(p_name); if (PS(id)) efree(PS(id)); + if (PS(session_status) & PS_ACTIVE) { + efree(old); + php_error(E_NOTICE, "%s() cannot set session id once session +is started.", + get_active_function_name(TSRMLS_C)); + RETURN_FALSE; + } + convert_to_string_ex(p_name); PS(id) = estrndup(Z_STRVAL_PP(p_name), Z_STRLEN_PP(p_name)); } @@ -1181,6 +1228,13 @@ WRONG_PARAM_COUNT; if (ac == 1) { + if (PS(session_status) & (PS_ACTIVE|PS_ERROR)) { + efree(old); + php_error(E_NOTICE, "%s() cannot set session module name once +session is started.", + get_active_function_name(TSRMLS_C)); + RETURN_FALSE; + } + convert_to_string_ex(p_cache_limiter); zend_alter_ini_entry("session.cache_limiter", sizeof("session.cache_limiter"), Z_STRVAL_PP(p_cache_limiter), Z_STRLEN_PP(p_cache_limiter), PHP_INI_USER, PHP_INI_STAGE_RUNTIME); } @@ -1252,7 +1306,7 @@ WRONG_PARAM_COUNT; } - if (PS(session_status) == php_session_none) + if (PS(session_status) & PS_NONE) php_session_start(TSRMLS_C); for (i = 0; i < argc; i++) { @@ -1276,7 +1330,13 @@ if (ac != 1 || zend_get_parameters_ex(ac, &p_name) == FAILURE) WRONG_PARAM_COUNT; - + + if (!(PS(session_status) & PS_ACTIVE)) { + php_error(E_NOTICE, "%s() cannot be used unless session is started.", + get_active_function_name(TSRMLS_C)); + RETURN_FALSE; + } + convert_to_string_ex(p_name); PS_DEL_VARL(Z_STRVAL_PP(p_name), Z_STRLEN_PP(p_name)); @@ -1296,6 +1356,12 @@ if (ac != 1 || zend_get_parameters_ex(ac, &p_name) == FAILURE) WRONG_PARAM_COUNT; + if (!(PS(session_status) & PS_ACTIVE)) { + php_error(E_NOTICE, "%s() cannot be used unless session is started.", + get_active_function_name(TSRMLS_C)); + RETURN_FALSE; + } + convert_to_string_ex(p_name); if (zend_hash_find(&PS(vars), Z_STRVAL_PP(p_name), @@ -1372,7 +1438,7 @@ char *variable; ulong num_key; - if (PS(session_status) == php_session_none) + if (PS(session_status) & PS_NONE) RETURN_FALSE; if (PG(register_globals)) { @@ -1393,7 +1459,7 @@ PHPAPI void session_adapt_url(const char *url, size_t urllen, char **new, size_t *newlen TSRMLS_DC) { - if (PS(apply_trans_sid) && (PS(session_status) == php_session_active)) { + if (PS(apply_trans_sid) && (PS(session_status) & PS_ACTIVE)) { *new = url_adapt_single_url(url, urllen, PS(session_name), PS(id), newlen TSRMLS_CC); } } @@ -1403,7 +1469,7 @@ { zend_hash_init(&PS(vars), 0, NULL, NULL, 0); PS(id) = NULL; - PS(session_status) = php_session_none; + PS(session_status) = PS_NONE; PS(mod_data) = NULL; PS(output_handler_registered) = 0; } @@ -1424,8 +1490,9 @@ { php_rinit_session_globals(TSRMLS_C); - if (PS(mod) == NULL) { + if (PS(mod) == NULL || PS(rinit_mod)) { char *value; + PS(rinit_mod) = 0; value = zend_ini_string("session.save_handler", sizeof("session.save_handler"), 0); if (value) { @@ -1434,7 +1501,7 @@ if (!PS(mod)) { /* current status is unusable */ - PS(session_status) = php_session_disabled; + PS(session_status) = PS_DISABLED; return SUCCESS; } } @@ -1448,9 +1515,9 @@ static void php_session_flush(TSRMLS_D) { - if(PS(session_status)==php_session_active) { + if(PS(session_status) & PS_ACTIVE) { php_session_save_current_state(TSRMLS_C); - PS(session_status)=php_session_none; + PS(session_status) = PS_DISABLED; } } @@ -1468,6 +1535,7 @@ } php_session_flush(TSRMLS_C); php_rshutdown_session_globals(TSRMLS_C); + PS(session_status) = PS_DISABLED; return SUCCESS; } /* }}} */
-- PHP Install Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php