From b9fb71030f38e17b0fc6b2c3639240066a62875f Mon Sep 17 00:00:00 2001 From: skodak Date: Mon, 19 Jan 2009 08:03:55 +0000 Subject: [PATCH] MDL-17942 reimplemented detection of mysql max_packet_size problems --- index.php | 2 +- lang/en_utf8/error.php | 1 + lib/db/install.xml | 7 ++-- lib/db/upgrade.php | 5 +-- lib/sessionlib.php | 93 ++++++++++++++++++++++++------------------ login/index.php | 2 +- version.php | 2 +- 7 files changed, 62 insertions(+), 50 deletions(-) diff --git a/index.php b/index.php index 5730fed538..dec4d08f77 100644 --- a/index.php +++ b/index.php @@ -47,7 +47,7 @@ define('BLOCK_R_MAX_WIDTH', $rmax); // check if major upgrade needed - also present in login/index.php - if (empty($CFG->version) or (int)$CFG->version < 2009011600) { //1.9 or older + if (empty($CFG->version) or (int)$CFG->version < 2009011900) { //1.9 or older @require_logout(); redirect("$CFG->wwwroot/$CFG->admin/"); } diff --git a/lang/en_utf8/error.php b/lang/en_utf8/error.php index 8e0a5d9459..5a2ca1c5ea 100644 --- a/lang/en_utf8/error.php +++ b/lang/en_utf8/error.php @@ -191,6 +191,7 @@ $string['dbdriverproblem'] = '

Error: database driver problem detected

$string['dbupdatefailed'] = 'Database update failed'; $string['dbsessionbroken'] = 'Serious database session problem detected.

Please notify server administrator.'; $string['dbsessionhandlerproblem'] = 'Setting up of database session failed.

Please notify server administrator.'; +$string['dbsessionmysqlpacketsize'] = 'Serious session error detected.

Please notify administrator, this problem is most probably caused by small value in max_packet_size MySQL setting.'; $string['ddlexecuteerror'] = 'DDL sql execution error'; $string['ddlfieldalreadyexists'] = 'Field \"$a\" does not exist'; $string['ddlfieldnotexist'] = 'Field \"$a->fieldname\" does not exist in table \"$a->tablename\"'; diff --git a/lib/db/install.xml b/lib/db/install.xml index b33b7bac01..2b0f0a2472 100644 --- a/lib/db/install.xml +++ b/lib/db/install.xml @@ -1,5 +1,5 @@ - @@ -442,9 +442,8 @@ - - - + + diff --git a/lib/db/upgrade.php b/lib/db/upgrade.php index 2ea3ddffab..1ebdd0084d 100644 --- a/lib/db/upgrade.php +++ b/lib/db/upgrade.php @@ -1323,7 +1323,7 @@ function xmldb_main_upgrade($oldversion) { upgrade_main_savepoint($result, 2009011303); } - if ($result && $oldversion < 2009011600) { + if ($result && $oldversion < 2009011900) { /// Define table sessions2 to be dropped $table = new xmldb_table('sessions2'); @@ -1350,7 +1350,6 @@ function xmldb_main_upgrade($oldversion) { $table->add_field('sid', XMLDB_TYPE_CHAR, '128', null, XMLDB_NOTNULL, null, null, null, null); $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, null); $table->add_field('sessdata', XMLDB_TYPE_TEXT, 'big', null, null, null, null, null, null); - $table->add_field('sessdatahash', XMLDB_TYPE_CHAR, '40', null, null, null, null, null, null); $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, null); $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, null); $table->add_field('firstip', XMLDB_TYPE_CHAR, '45', null, null, null, null, null, null); @@ -1370,7 +1369,7 @@ function xmldb_main_upgrade($oldversion) { $dbman->create_table($table); /// Main savepoint reached - upgrade_main_savepoint($result, 2009011600); + upgrade_main_savepoint($result, 2009011900); } diff --git a/lib/sessionlib.php b/lib/sessionlib.php index 84a70fafe6..81251f1ac7 100644 --- a/lib/sessionlib.php +++ b/lib/sessionlib.php @@ -60,7 +60,7 @@ abstract class session_stub implements moodle_session { global $CFG; if (!defined('NO_MOODLE_COOKIES')) { - if (empty($CFG->version) or $CFG->version < 2009011600) { + if (empty($CFG->version) or $CFG->version < 2009011900) { // no session before sessions table gets greated define('NO_MOODLE_COOKIES', true); } else if (CLI_SCRIPT) { @@ -322,6 +322,15 @@ class database_session extends session_stub { global $DB; $this->database = $DB; parent::__construct(); + + if (!empty($this->record->state)) { + // something is very wrong + session_kill($this->record->sid); + + if ($this->record->state == 9) { + print_error('dbsessionmysqlpacketsize', 'error'); + } + } } protected function init_session_storage() { @@ -372,7 +381,6 @@ class database_session extends session_stub { $record->state = 0; $record->sid = $sid; $record->sessdata = null; - $record->sessdatahash = null; $record->userid = 0; $record->timecreated = $record->timemodified = time(); $record->firstip = $record->lastip = getremoteaddr(); @@ -415,7 +423,6 @@ class database_session extends session_stub { //time out session $record->state = 0; $record->sessdata = null; - $record->sessdatahash = null; $record->userid = 0; $record->timecreated = $record->timemodified = time(); $record->firstip = $record->lastip = getremoteaddr(); @@ -428,20 +435,7 @@ class database_session extends session_stub { } } - if ($record->sessdata !== null) { - if (md5($record->sessdata) !== $record->sessdatahash) { - // probably this is caused by misconfigured mysql - the allowed request size might be too small - try { - $this->database->delete_records('sessions', array('sid'=>$record->sid)); - } catch (dml_exception $ignored) { - } - print_error('dbsessionbroken', 'error'); - } - - $data = base64_decode($record->sessdata); - } else { - $data = ''; - } + $data = is_null($record->sessdata) ? '' : base64_decode($record->sessdata); unset($record->sessdata); // conserve memory $this->record = $record; @@ -452,36 +446,55 @@ class database_session extends session_stub { public function handler_write($sid, $session_data) { global $USER; - try { - if (isset($this->record->id)) { - $record->sid = $sid; // might be regenerating sid - $this->record->sessdata = base64_encode($session_data); // there might be some binary mess :-( - $this->record->sessdatahash = md5($this->record->sessdata); - $this->record->userid = empty($USER->realuser) ? $USER->id : $USER->realuser; - $this->record->timemodified = time(); - $this->record->lastip = getremoteaddr(); + $userid = 0; + if (!empty($USER->realuser)) { + $userid = $USER->realuser; + } else if (!empty($USER->id)) { + $userid = $USER->id; + } + + if (isset($this->record->id)) { + $record->state = 0; + $record->sid = $sid; // might be regenerating sid + $this->record->sessdata = base64_encode($session_data); // there might be some binary mess :-( + $this->record->userid = $userid; + $this->record->timemodified = time(); + $this->record->lastip = getremoteaddr(); - // TODO: verify session changed before doing update + // TODO: verify session changed before doing update + try { $this->database->update_record_raw('sessions', $this->record); + } catch (dml_exception $ex) { + if ($this->database->get_dbfamily() === 'mysql') { + try { + $this->database->set_field('sessions', 'state', 9, array('id'=>$this->record->id)); + } catch (Exception $ignored) { - } else { - // session already destroyed - $record = new object(); - $record->state = 0; - $record->sid = $sid; - $record->sessdata = base64_encode($session_data); // there might be some binary mess :-( - $record->sessdatahash = md5($record->sessdata); - $record->userid = empty($USER->realuser) ? $USER->id : $USER->realuser; - $record->timecreated = $record->timemodified = time(); - $record->firstip = $record->lastip = getremoteaddr(); - $record->id = $this->database->insert_record_raw('sessions', $record); - $this->record = $record; + } + error_log('Can not write session - please verify max_packet_size is at least 4MB'); + } else { + error_log('Can not write session'); + } + } + } else { + // session already destroyed + $record = new object(); + $record->state = 0; + $record->sid = $sid; + $record->sessdata = base64_encode($session_data); // there might be some binary mess :-( + $record->userid = $userid; + $record->timecreated = $record->timemodified = time(); + $record->firstip = $record->lastip = getremoteaddr(); + $record->id = $this->database->insert_record_raw('sessions', $record); + $this->record = $record; + + try { $this->database->get_session_lock($this->record->id); + } catch (dml_exception $ex) { + error_log('Can not write new session'); } - } catch (dml_exception $ex) { - error_log('Can not write session'); } return true; diff --git a/login/index.php b/login/index.php index 385dce6156..68fedfb618 100644 --- a/login/index.php +++ b/login/index.php @@ -4,7 +4,7 @@ require_once("../config.php"); /// check if major upgrade needed - also present in /index.php - if ((int)$CFG->version < 2009011600) { //1.9 or older + if ((int)$CFG->version < 2009011900) { //1.9 or older @require_logout(); redirect("$CFG->wwwroot/$CFG->admin/"); } diff --git a/version.php b/version.php index 707ab024dd..c035863cab 100644 --- a/version.php +++ b/version.php @@ -6,7 +6,7 @@ // This is compared against the values stored in the database to determine // whether upgrades should be performed (see lib/db/*.php) - $version = 2009011600; // YYYYMMDD = date of the last version bump + $version = 2009011900; // YYYYMMDD = date of the last version bump // XX = daily increments $release = '2.0 dev (Build: 20090119)'; // Human-friendly version name -- 2.39.5