Подтвердить что ты не робот

Session_start зависает

так как через несколько часов наш сервер зависает каждый раз, когда вы выполняете session_start.

В целях тестирования я создал script, который выглядит так:

<?php
session_start();
?>

Вызов его из консоли зависает, и он не может быть остановлен с помощью ctrl-c, только kill -9 работает. То же самое для вызова через Apache. /var/lib/php/session/ остается пустым, но разрешения абсолютно точны, www может писать, а также имеет разрешения на чтение для всех родительских папок.

По словам админов, на сервере не было изменений, и для сеансов не было зарегистрировано никакого специального кода. Сервер CentOS 4 или 5, и вчера все работало отлично. Мы перезагрузили сервер и обновили PHP, но ничего не изменилось.

У меня кончились идеи, любые предложения?

UPDATE

Мы решили эту проблему, перемещая проект на другой сервер, поэтому, пока проблема все еще существует на одном сервере, нет необходимости в немедленном решении проблемы. Я буду держать вопрос открытым, если у кого-то есть идея для других, имеющих аналогичную проблему в будущем.

4b9b3361

Ответ 1

Есть много причин для этого, вот несколько из них:

A. Файл сеанса можно открыть исключительно. Если по какой-либо причине блокировка файла не освобождается должным образом, это приводит к тому, что session_start() бесконечно зависает в любых будущих исполнениях script. Обход проблемы: используйте session_set_save_handler() и убедитесь, что функция записи использует fopen($file, 'w') instead of fopen($file, 'x')

B. Никогда не используйте следующее в файле php.ini(файл энтропии на "/dev/random" ), это приведет к зависанию session_start():

<?php
ini_set("session.entropy_file", "/dev/random");
ini_set("session.entropy_length", "512");
?>

С. session_start() нужен каталог для записи.

Вы можете использовать Apache plus PHP в обычной учетной записи пользователя. Конечно, Apache должен слушать другой порт, чем 80 (например, 8080).

Обязательно выполните следующие действия: - создать временный каталог PREFIX/tmp - поместите php.ini в PREFIX/lib - отредактируйте php.ini и установите session.save_path в только что созданном каталоге

В противном случае ваши скрипты, похоже, будут "висеть" на session_start().

Ответ 2

Если это помогает:

В моем сценарии session_start() висел в то же время, когда я использовал отладчик XDebug в среде PHPStorm, IDE, в Windows. Я обнаружил, что была явная причина: всякий раз, когда я убивал сеанс отладки из PHPStorm, в следующий раз, когда я попытался запустить сеанс отладки, session_start() зависает.

Решение, если это ваш сценарий, заключается в том, чтобы перезапустить Apache каждый раз, когда вы убиваете сессию XDebug в своей среде IDE.

Ответ 3

У меня была странная проблема с этим.

Я использую CentOS 5.5x64, PHP 5.2.10-1. Чистый ANSI файл в корне с чем-то, кроме session_start(), висел. Сессия записывалась на диск и ошибок не возникало. Он просто висел.

Я попробовал все, что предложил Thariama, и проверил настройки компиляции PHP и т.д.

My Fix:

yum reinstall php;  /etc/init.d/httpd restart

Надеюсь, это поможет кому-то.

Для всех, кто жалуется на то, что 30 секунд простоя неприемлемы, это была необъяснимая проблема в совершенно новой, чистой установке ОС, а не в запущенной производственной машине. Это решение НЕ должно использоваться в рабочей среде.

Ответ 4

Проблема: -

Iv испытал (и исправил) проблему, когда сеансы на основе файлов зависают от запроса, а сеансы на основе базы данных выходят из синхронизации, сохраняя устаревшие данные сеанса (например, сохранение каждого сохранения сеанса в неправильном порядке).

Это вызвано любым последующим запросом, который загружает сеанс (одновременные запросы), например ajax, вставлять видео, где видеофайлы доставляются через php script, файл динамических ресурсов (например, script или css), поставляемый через PHP скрипт и т.д.

В файловых сеансах блокировка файлов предотвращает запись сеанса, что вызывает тупик между одновременными потоками запросов.

В сеансе, основанный на базе данных, последний завершающий поток запросов становится самым последним, так что, например, доставка видео script завершится после запроса страницы и перезапишет обновленный сеанс старыми данными сеанса.

Исправить: -

Если ваш ajax или ресурс доставки script не нужно использовать сеансы, тогда проще всего просто удалить из него сеанс.

В противном случае вам лучше всего сделать кофе и сделать следующее: -

  • Напишите или используйте обработчик сеанса (если это еще не так) в соответствии с http://www.php.net//manual/en/class.sessionhandler.php (многие другие примеры доступны через поиск Google).
  • В вашей функции обработчика сеанса write() добавьте код...

        // processes may declare their session as read only ...
        if(!empty($_SESSION['no_session_write'])) {
                unset($_SESSION['no_session_write']);
                return true;
        }
    
  • В вашем пакете ajax или доставки ресурсов php script добавьте код (после запуска сеанса)...

        $_SESSION['no_session_write'] = true;
    

Я понимаю, что это похоже на то, как много надувать, что должно быть крошечным исправлением, но, к сожалению, если вам нужно иметь одновременные запросы для каждой загрузки сеанса, тогда это необходимо.

ЗАМЕЧАНИЕ, если на ваш айакс или ресурс доставки script действительно нужно записать/сохранить данные, тогда вам нужно сделать это где-то, кроме как в сеансе, например в базе данных.

Ответ 6

Чтобы добавить другой ответ в микс для тех, кто собирается бананы, у меня был session_start(), который умирал только в отдельных случаях и сценариях. Причина, по которой моя сессия умирала, была в конечном счете потому, что я хранил много данных в них после особо интенсивного script, и, в конечном счете, вызов session_start() исчерпывал настройку "memory_limit" в php.ini.

После увеличения 'memory_limit', те session_start() вызовы больше не убивают мой script.