Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stack Overflow on database shutdown #24

Open
slackwarwick opened this issue Apr 5, 2018 · 4 comments
Open

Stack Overflow on database shutdown #24

slackwarwick opened this issue Apr 5, 2018 · 4 comments

Comments

@slackwarwick
Copy link

Firebird 2.5, C++ Builder 6.0.
Пытаюсь научить свою программу обрабатывать потерю соединения с БД. Для этого после старта программы делаю shutdown базы, и ловлю ошибку в TpFibErrorHandler::OnFIBErrorEvent. Но похоже, что программа вообще не доходит до вызова моей процедуры обработки. Происходит цепочка вызовов:
TpFibErrorHandler.DoOnErrorEvent -> TpFibErrorHandler.DefaultOnError -> .InternalClose -> <ошибка при закрытии транзакций> -><ошибка при закрытии запроса> -> TpFibErrorHandler.DoOnErrorEvent -> TpFibErrorHandler.DefaultOnError ... и так далее, из-за чего возникает переполнение стека.

@slackwarwick
Copy link
Author

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

@slackwarwick
Copy link
Author

Попробовал на другой версии FIB, более старой (6.9.9), официально купленной в свое время - нет, другие проблемы ушли, а проблема с shutdown остается.

@slackwarwick
Copy link
Author

В общем, я немного исследовал эту тему, и пришел к выводу, что с обработкой события SHUTDOWN у компонента FIB все несколько плоховато. Причем быстро это исправить пока непонятно, как.
Откуда берется бесконечная рекурсия:

В функции TpFibErrorHandler.DoOnErrorEvent сразу вызывается TpFibErrorHandler.DefaultOnError, в котором есть такие строки:

  if (IBErrorCode=isc_shutdown) and (FindDatabaseForObject(Sender)<>nil) then
   FindDatabaseForObject(Sender).InternalClose(True,True);

InternalClose внутри себя пытается закрыть транзакции и запросы, но при вызове TFIBQuery.Close опять же от базы приходит код ответа isc_shutdown, и генерируется ошибка, приводящая к вызову TpFibErrorHandler.DoOnErrorEvent.

Я попытался подавить ошибку isc_shutdown, заменив в TFIBQuery.Close проверку CheckStatusVector([isc_bad_stmt_handle, isc_dsql_cursor_close_err]) на проверку CheckStatusVector([isc_bad_stmt_handle, isc_dsql_cursor_close_err, isc_shutdown]) (и то же самое внутри TFIBQuery.FreeHandle).

Тогда бесконечная рекурсия не происходит, но и событие TpFIBDatabase.DoOnLostConnect тоже не вызывается, т.к. база уже закрыта.

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

Вот вроде бы в функции TpFIBDatabase.InternalClose есть параметр DBinShutDown, но он, кажется, нигде не используется.

@CyberMaxRu
Copy link

slackwarwick, я сделал ровно точно так же.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants