Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
integration
prechecker
Commits
38fc0130
Commit
38fc0130
authored
Sep 27, 2013
by
Petr Škoda
Browse files
MDL-42040 refactor core Moodle shutdown handlers logic
parent
56cc9b38
Changes
13
Hide whitespace changes
Inline
Side-by-side
admin/tool/dbtransfer/locallib.php
View file @
38fc0130
...
...
@@ -165,7 +165,7 @@ function tool_dbtransfer_get_drivers() {
function
tool_dbtransfer_create_maintenance_file
()
{
global
$CFG
;
re
gister
_shutdown_function
(
'tool_dbtransfer_maintenance_callback'
);
co
re_shutdown_
manager
::
register_
function
(
'tool_dbtransfer_maintenance_callback'
);
$options
=
new
stdClass
();
$options
->
trusted
=
false
;
...
...
backup/cc/cc_lib/gral_lib/cssparser.php
View file @
38fc0130
...
...
@@ -20,7 +20,7 @@ class cssparser {
function
cssparser
(
$html
=
true
)
{
// Register "destructor"
re
gister
_shutdown_function
(
array
(
&
$this
,
"finalize"
));
co
re_shutdown_
manager
::
register_
function
(
array
(
&
$this
,
"finalize"
));
$this
->
html
=
(
$html
!=
false
);
$this
->
Clear
();
}
...
...
lib/classes/session/database.php
View file @
38fc0130
...
...
@@ -79,8 +79,6 @@ class database extends handler {
if
(
!
$result
)
{
throw
new
exception
(
'dbsessionhandlerproblem'
,
'error'
);
}
register_shutdown_function
(
array
(
$this
,
'handler_shutdown'
));
}
/**
...
...
@@ -305,11 +303,4 @@ class database extends handler {
$this
->
database
->
delete_records_select
(
'sessions'
,
'userid = 0 AND timemodified < :purgebefore'
,
$params
);
return
true
;
}
/**
* This makes sure the session is written to disk at the end of request.
*/
public
function
handler_shutdown
()
{
$this
->
database
->
dispose
();
}
}
lib/classes/shutdown_manager.php
0 → 100644
View file @
38fc0130
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Shutdown management class.
*
* @package core
* @copyright 2013 Petr Skoda {@link http://skodak.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined
(
'MOODLE_INTERNAL'
)
||
die
();
/**
* Shutdown management class.
*
* @package core
* @copyright 2013 Petr Skoda {@link http://skodak.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class
core_shutdown_manager
{
/** @var array list of custom callbacks */
protected
static
$callbacks
=
array
();
/** @var bool is this manager already registered? */
protected
static
$registered
=
false
;
/**
* Register self as main shutdown handler.
*
* @private to be called from lib/setup.php only!
*/
public
static
function
initialize
()
{
if
(
self
::
$registered
)
{
debugging
(
'Shutdown manager is already initialised!'
);
}
self
::
$registered
=
true
;
register_shutdown_function
(
array
(
'core_shutdown_manager'
,
'shutdown_handler'
));
}
/**
* Register custom shutdown function.
*
* @param callable $callback
* @param array $params
*/
public
static
function
register_function
(
$callback
,
array
$params
=
null
)
{
self
::
$callbacks
[]
=
array
(
$callback
,
$params
);
}
/**
* @private - do NOT call directly.
*/
public
static
function
shutdown_handler
()
{
global
$DB
;
// Custom stuff first.
foreach
(
self
::
$callbacks
as
$data
)
{
list
(
$callback
,
$params
)
=
$data
;
try
{
if
(
!
is_callable
(
$callback
))
{
error_log
(
'Invalid custom shutdown function detected '
.
var_export
(
$callback
,
true
));
continue
;
}
if
(
$params
===
null
)
{
call_user_func
(
$callback
);
}
else
{
call_user_func_array
(
$callback
,
$params
);
}
}
catch
(
Exception
$e
)
{
error_log
(
'Exception ignored in shutdown function '
.
var_export
(
$callback
,
true
)
.
':'
.
$e
->
getMessage
());
}
}
// Handle DB transactions, session need to be written afterwards
// in order to maintain consistency in all session handlers.
if
(
$DB
->
is_transaction_started
())
{
if
(
!
defined
(
'PHPUNIT_TEST'
)
or
!
PHPUNIT_TEST
)
{
// This should not happen, it usually indicates wrong catching of exceptions,
// because all transactions should be finished manually or in default exception handler.
$backtrace
=
$DB
->
get_transaction_start_backtrace
();
error_log
(
'Potential coding error - active database transaction detected during request shutdown:'
.
"
\n
"
.
format_backtrace
(
$backtrace
,
true
));
}
$DB
->
force_transaction_rollback
();
}
// Close sessions - do it here to make it consistent for all session handlers.
\
core\session\manager
::
write_close
();
// Other cleanup.
self
::
request_shutdown
();
// Stop profiling.
if
(
function_exists
(
'profiling_is_running'
))
{
if
(
profiling_is_running
())
{
profiling_stop
();
}
}
// NOTE: do not dispose $DB and MUC here, they might be used from legacy shutdown functions.
}
/**
* Standard shutdown sequence.
*/
protected
static
function
request_shutdown
()
{
global
$CFG
;
// Help apache server if possible.
$apachereleasemem
=
false
;
if
(
function_exists
(
'apache_child_terminate'
)
&&
function_exists
(
'memory_get_usage'
)
&&
ini_get_bool
(
'child_terminate'
))
{
$limit
=
(
empty
(
$CFG
->
apachemaxmem
)
?
64
*
1024
*
1024
:
$CFG
->
apachemaxmem
);
// 64MB default.
if
(
memory_get_usage
()
>
get_real_size
(
$limit
))
{
$apachereleasemem
=
$limit
;
@
apache_child_terminate
();
}
}
// Deal with perf logging.
if
(
defined
(
'MDL_PERF'
)
||
(
!
empty
(
$CFG
->
perfdebug
)
and
$CFG
->
perfdebug
>
7
))
{
if
(
$apachereleasemem
)
{
error_log
(
'Mem usage over '
.
$apachereleasemem
.
': marking Apache child for reaping.'
);
}
if
(
defined
(
'MDL_PERFTOLOG'
))
{
$perf
=
get_performance_info
();
error_log
(
"PERF: "
.
$perf
[
'txt'
]);
}
if
(
defined
(
'MDL_PERFINC'
))
{
$inc
=
get_included_files
();
$ts
=
0
;
foreach
(
$inc
as
$f
)
{
if
(
preg_match
(
':^/:'
,
$f
))
{
$fs
=
filesize
(
$f
);
$ts
+=
$fs
;
$hfs
=
display_size
(
$fs
);
error_log
(
substr
(
$f
,
strlen
(
$CFG
->
dirroot
))
.
" size:
$fs
(
$hfs
)"
,
null
,
null
,
0
);
}
else
{
error_log
(
$f
,
null
,
null
,
0
);
}
}
if
(
$ts
>
0
)
{
$hts
=
display_size
(
$ts
);
error_log
(
"Total size of files included:
$ts
(
$hts
)"
);
}
}
}
}
}
lib/dml/moodle_database.php
View file @
38fc0130
...
...
@@ -336,6 +336,19 @@ abstract class moodle_database {
return
false
;
}
/**
* Returns transaction trace for debugging purposes.
* @private to be used by core only
* @return array or null if not in transaction.
*/
public
function
get_transaction_start_backtrace
()
{
if
(
!
$this
->
transactions
)
{
return
null
;
}
$lowesttransaction
=
end
(
$this
->
transactions
);
return
$lowesttransaction
->
get_backtrace
();
}
/**
* Closes the database connection and releases all resources
* and memory (especially circular memory references).
...
...
@@ -348,24 +361,8 @@ abstract class moodle_database {
}
$this
->
disposed
=
true
;
if
(
$this
->
transactions
)
{
// this should not happen, it usually indicates wrong catching of exceptions,
// because all transactions should be finished manually or in default exception handler.
// unfortunately we can not access global $CFG any more and can not print debug,
// the diagnostic info should be printed in footer instead
$lowesttransaction
=
end
(
$this
->
transactions
);
$backtrace
=
$lowesttransaction
->
get_backtrace
();
if
(
defined
(
'PHPUNIT_TEST'
)
and
PHPUNIT_TEST
)
{
//no need to log sudden exits in our PHPUnit test cases
}
else
{
error_log
(
'Potential coding error - active database transaction detected when disposing database:'
.
"
\n
"
.
format_backtrace
(
$backtrace
,
true
));
}
$this
->
force_transaction_rollback
();
}
// Always terminate sessions here to make it consistent,
// this is needed because we need to save session to db before closing it.
\
core\session\manager
::
write_close
();
$this
->
used_for_db_sessions
=
false
;
if
(
$this
->
temptables
)
{
$this
->
temptables
->
dispose
();
...
...
@@ -376,9 +373,6 @@ abstract class moodle_database {
$this
->
database_manager
=
null
;
}
$this
->
tables
=
null
;
// We do not need the MUC cache any more,
// if we did not keep it as property it might be already gone before we saved the session.
$this
->
metacache
=
null
;
}
...
...
@@ -2330,7 +2324,7 @@ abstract class moodle_database {
}
// now enable transactions again
$this
->
transactions
=
array
();
// unfortunately all unfinished exceptions are kept in memory
$this
->
transactions
=
array
();
$this
->
force_rollback
=
false
;
}
...
...
lib/filelib.php
View file @
38fc0130
...
...
@@ -2179,7 +2179,7 @@ function send_temp_file($path, $filename, $pathisstring=false) {
print_error
(
'filenotfound'
,
'error'
,
$CFG
->
wwwroot
.
'/'
);
}
// executed after normal finish or abort
@
register
_shutdown_function
(
'send_temp_file_finished'
,
$path
);
core
_shutdown_
manager
::
register_
function
(
'send_temp_file_finished'
,
array
(
$path
)
)
;
}
// if user is using IE, urlencode the filename so that multibyte file name will show up correctly on popup
...
...
lib/moodlelib.php
View file @
38fc0130
...
...
@@ -8542,58 +8542,6 @@ function fullclone($thing) {
return unserialize(serialize($thing));
}
/**
* This function expects to called during shutdown should be set via register_shutdown_function() in lib/setup.php .
*
* @return void
*/
function
moodle_request_shutdown
()
{
global
$CFG
;
// Help apache server if possible.
$apachereleasemem
=
false
;
if
(
function_exists
(
'apache_child_terminate'
)
&&
function_exists
(
'memory_get_usage'
)
&&
ini_get_bool
(
'child_terminate'
))
{
$limit
=
(
empty
(
$CFG
->
apachemaxmem
)
?
64
*
1024
*
1024
:
$CFG
->
apachemaxmem
);
// 64MB default.
if
(
memory_get_usage
()
>
get_real_size
(
$limit
))
{
$apachereleasemem
=
$limit
;
@
apache_child_terminate
();
}
}
// Deal with perf logging.
if
(
defined
(
'MDL_PERF'
)
||
(
!
empty
(
$CFG
->
perfdebug
)
and
$CFG
->
perfdebug
>
7
))
{
if
(
$apachereleasemem
)
{
error_log
(
'Mem usage over '
.
$apachereleasemem
.
': marking Apache child for reaping.'
);
}
if
(
defined
(
'MDL_PERFTOLOG'
))
{
$perf
=
get_performance_info
();
error_log
(
"PERF: "
.
$perf
[
'txt'
]);
}
if
(
defined
(
'MDL_PERFINC'
))
{
$inc
=
get_included_files
();
$ts
=
0
;
foreach
(
$inc
as
$f
)
{
if
(
preg_match
(
':^/:'
,
$f
))
{
$fs
=
filesize
(
$f
);
$ts
+=
$fs
;
$hfs
=
display_size
(
$fs
);
error_log
(
substr
(
$f
,
strlen
(
$CFG
->
dirroot
))
.
" size:
$fs
(
$hfs
)"
,
null
,
null
,
0
);
}
else
{
error_log
(
$f
,
null
,
null
,
0
);
}
}
if
(
$ts
>
0
)
{
$hts
=
display_size
(
$ts
);
error_log
(
"Total size of files included:
$ts
(
$hts
)"
);
}
}
}
}
/**
* If new messages are waiting for the current user, then insert
* JavaScript to pop up the messaging window into the page
...
...
lib/navigationlib.php
View file @
38fc0130
...
...
@@ -4668,7 +4668,7 @@ class navigation_cache {
public
function
volatile
(
$setting
=
true
)
{
if
(
self
::
$volatilecaches
===
null
)
{
self
::
$volatilecaches
=
array
();
re
gister
_shutdown_function
(
array
(
'navigation_cache'
,
'destroy_volatile_caches'
));
co
re_shutdown_
manager
::
register_
function
(
array
(
'navigation_cache'
,
'destroy_volatile_caches'
));
}
if
(
$setting
)
{
...
...
lib/outputrenderers.php
View file @
38fc0130
...
...
@@ -883,9 +883,6 @@ class core_renderer extends renderer_base {
$performanceinfo
=
''
;
if
(
defined
(
'MDL_PERF'
)
||
(
!
empty
(
$CFG
->
perfdebug
)
and
$CFG
->
perfdebug
>
7
))
{
$perf
=
get_performance_info
();
if
(
defined
(
'MDL_PERFTOLOG'
)
&&
!
function_exists
(
'register_shutdown_function'
))
{
error_log
(
"PERF: "
.
$perf
[
'txt'
]);
}
if
(
defined
(
'MDL_PERFTOFOOT'
)
||
debugging
()
||
$CFG
->
perfdebug
>
7
)
{
$performanceinfo
=
$perf
[
'html'
];
}
...
...
lib/setup.php
View file @
38fc0130
...
...
@@ -372,9 +372,7 @@ if (defined('ABORT_AFTER_CONFIG')) {
// Early profiling start, based exclusively on config.php $CFG settings
if
(
!
empty
(
$CFG
->
earlyprofilingenabled
))
{
require_once
(
$CFG
->
libdir
.
'/xhprof/xhprof_moodle.php'
);
if
(
profiling_start
())
{
register_shutdown_function
(
'profiling_stop'
);
}
profiling_start
();
}
/**
...
...
@@ -622,6 +620,9 @@ if (!isset($CFG->debugdisplay)) {
ini_set
(
'display_errors'
,
'1'
);
}
// Register our shutdown manager, do NOT use register_shutdown_function().
core_shutdown_manager
::
initialize
();
// Verify upgrade is not running unless we are in a script that needs to execute in any case
if
(
!
defined
(
'NO_UPGRADE_CHECK'
)
and
isset
(
$CFG
->
upgraderunning
))
{
if
(
$CFG
->
upgraderunning
<
time
())
{
...
...
@@ -642,11 +643,6 @@ if (function_exists('gc_enable')) {
gc_enable
();
}
// Register default shutdown tasks - such as Apache memory release helper, perf logging, etc.
if
(
function_exists
(
'register_shutdown_function'
))
{
register_shutdown_function
(
'moodle_request_shutdown'
);
}
// detect unsupported upgrade jump as soon as possible - do not change anything, do not use system functions
if
(
!
empty
(
$CFG
->
version
)
and
$CFG
->
version
<
2007101509
)
{
print_error
(
'upgraderequires19'
,
'error'
);
...
...
@@ -773,9 +769,7 @@ if (!PHPUNIT_TEST and !defined('BEHAT_TEST')) {
// Late profiling, only happening if early one wasn't started
if
(
!
empty
(
$CFG
->
profilingenabled
))
{
require_once
(
$CFG
->
libdir
.
'/xhprof/xhprof_moodle.php'
);
if
(
profiling_start
())
{
register_shutdown_function
(
'profiling_stop'
);
}
profiling_start
();
}
// Process theme change in the URL.
...
...
lib/upgrade.txt
View file @
38fc0130
...
...
@@ -41,6 +41,7 @@ information provided here is intended especially for developers.
* Each plugin should include version information in version.php.
* Module and block tables do not contain version column any more, use get_config('xx_yy', 'version') instead.
* $USER->password field is intentionally unset so that session data does not contain password hashes.
* Use core_shutdown_manager::register_function() instead of register_shutdown_function().
DEPRECATIONS:
Various previously deprecated functions have now been altered to throw DEBUG_DEVELOPER debugging notices
...
...
lib/upgradelib.php
View file @
38fc0130
...
...
@@ -1257,7 +1257,7 @@ function upgrade_started($preinstall=false) {
}
ignore_user_abort
(
true
);
re
gister
_shutdown_function
(
'upgrade_finished_handler'
);
co
re_shutdown_
manager
::
register_
function
(
'upgrade_finished_handler'
);
upgrade_setup_debug
(
true
);
set_config
(
'upgraderunning'
,
time
()
+
300
);
$started
=
true
;
...
...
lib/weblib.php
View file @
38fc0130
...
...
@@ -2615,13 +2615,6 @@ function redirect($url, $message='', $delay=-1) {
$delay
=
0
;
}
if
(
defined
(
'MDL_PERF'
)
||
(
!
empty
(
$CFG
->
perfdebug
)
and
$CFG
->
perfdebug
>
7
))
{
if
(
defined
(
'MDL_PERFTOLOG'
)
&&
!
function_exists
(
'register_shutdown_function'
))
{
$perf
=
get_performance_info
();
error_log
(
"PERF: "
.
$perf
[
'txt'
]);
}
}
// Make sure the session is closed properly, this prevents problems in IIS
// and also some potential PHP shutdown issues.
\
core\session\manager
::
write_close
();
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment