public static function start() {
        global $CFG, $DB, $PERF;

        if (isset(self::$sessionactive)) {
            debugging('Session was already started!', DEBUG_DEVELOPER);
            return;
        }

        // Grab the time before session lock starts.
        $PERF->sessionlock['start'] = microtime(true);
        self::load_handler();

        // Init the session handler only if everything initialised properly in lib/setup.php file
        // and the session is actually required.
        if (empty($DB) or empty($CFG->version) or !defined('NO_MOODLE_COOKIES') or NO_MOODLE_COOKIES or CLI_SCRIPT) {
            self::$sessionactive = false;
            self::init_empty_session();
            return;
        }

        try {
            self::$handler->init();
            self::prepare_cookies();
            $isnewsession = empty($_COOKIE[session_name()]);

            if (!self::$handler->start()) {
                // Could not successfully start/recover session.
                throw new \core\session\exception(get_string('servererror'));
            }

            // Grab the time when session lock starts.
            $PERF->sessionlock['gained'] = microtime(true);
            $PERF->sessionlock['wait'] = $PERF->sessionlock['gained'] - $PERF->sessionlock['start'];
            self::initialise_user_session($isnewsession);
            self::$sessionactive = true; // Set here, so the session can be cleared if the security check fails.
            self::check_security();

            // Link global $USER and $SESSION,
            // this is tricky because PHP does not allow references to references
            // and global keyword uses internally once reference to the $GLOBALS array.
            // The solution is to use the $GLOBALS['USER'] and $GLOBALS['$SESSION']
            // as the main storage of data and put references to $_SESSION.
            $GLOBALS['USER'] = $_SESSION['USER'];
            $_SESSION['USER'] =& $GLOBALS['USER'];
            $GLOBALS['SESSION'] = $_SESSION['SESSION'];
            $_SESSION['SESSION'] =& $GLOBALS['SESSION'];

        } catch (\Exception $ex) {
            self::init_empty_session();
            self::$sessionactive = false;
            throw $ex;
        }
    }