|
Дополнительная информация при ошибке в UDF
|
|||
---|---|---|---|
#18+
Hello, Cybermax! You wrote on 22 декабря 2015 г. 12:04:33: Cybermax> С другой стороны, кто-нибудь может сказать, зачем FB вообще падает? > При вызове UDF достаточно же сделать try/catch, не?дык он и делает. об чём тебе и сообщает в логе. Posted via ActualForum NNTP Server 1.5 ... |
|||
:
Нравится:
Не нравится:
|
|||
22.12.2015, 12:04 |
|
Дополнительная информация при ошибке в UDF
|
|||
---|---|---|---|
#18+
CyberMax, дельфийские исключения движком FB не перехватываются. В UDR кстати это можно. Я чуть позже покажу как ... |
|||
:
Нравится:
Не нравится:
|
|||
22.12.2015, 12:10 |
|
Дополнительная информация при ошибке в UDF
|
|||
---|---|---|---|
#18+
Мимопроходящий, Симонов Денис, Тогда я не совсем понимаю механику этой ситуации. Движок вызывает UDF через обычный вызов процедуры в DLL. Если там происходит дельфийское исключение, то ...? ... |
|||
:
Нравится:
Не нравится:
|
|||
22.12.2015, 12:19 |
|
Дополнительная информация при ошибке в UDF
|
|||
---|---|---|---|
#18+
CyberMax, по уму возникшее исключение должно сформировать статус вектор и кинуть ошибку в виде обычной ошибки которая генерируется подобно PSQL оператору EXCEPTION. Т.е. ошибка просто должна высветится у клиента без завершения работы сервера. В UDF статус вектор в который можно засунуть ошибку отсутствует. Чего там делает при этом FB я не знаю, но вероятно просто кидает bugcheck. Появятся источники света может и расскажут. ... |
|||
:
Нравится:
Не нравится:
|
|||
22.12.2015, 12:25 |
|
Дополнительная информация при ошибке в UDF
|
|||
---|---|---|---|
#18+
CyberMaxМимопроходящий, Симонов Денис, Тогда я не совсем понимаю механику этой ситуации. Движок вызывает UDF через обычный вызов процедуры в DLL. Если там происходит дельфийское исключение, то ...? А оттуда приходит: "нагажено в общую память неизвестно куда и непонятно сколько. выяснили только вот счас и чиста случайно." Что делает нормальный сервер в ситуации когда ему нагадили в душу? Умывает руки. ... |
|||
:
Нравится:
Не нравится:
|
|||
22.12.2015, 12:28 |
|
Дополнительная информация при ошибке в UDF
|
|||
---|---|---|---|
#18+
pastor, Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12.
Это выполнился код: Код: pascal 1. 2. 3. 4.
Тоже память загажена? ... |
|||
:
Нравится:
Не нравится:
|
|||
22.12.2015, 12:40 |
|
Дополнительная информация при ошибке в UDF
|
|||
---|---|---|---|
#18+
CyberMax, да. Эксепшн созданный в Delphi не может быть обработан. Кроме того, освободить память которая была выделена в момент создания исключения EDivByZero.Create('DivZero') FB тоже не может. ... |
|||
:
Нравится:
Не нравится:
|
|||
22.12.2015, 12:44 |
|
Дополнительная информация при ошибке в UDF
|
|||
---|---|---|---|
#18+
CyberMax, dll может быть создана любым компилятором. ФБ скомпилирован на C++. Как обрабатывать исключения, возникающие в dll, написанные неизвестно на чем - ... никак. Об этом Харрисон уже давно говорила - при реализации udf было два варианта. либо тупо давать грузить функции из .so, без всякого контроля, но зато чтобы быстро работало, или обрамлять функции тучей проверок, т.е. чтобы медленно, но надежно. Решили забить болт, и грузить так. ... |
|||
:
Нравится:
Не нравится:
|
|||
22.12.2015, 13:02 |
|
Дополнительная информация при ошибке в UDF
|
|||
---|---|---|---|
#18+
Симонов ДенисDBConstructor, а где гарантия что Access violation произошёл внутри UDF, а не в момент освобождения выделенной в ней памяти движком FB? Хотя текст ошибки вроде указывает на это. Получить в UDF исключение Access Violation, отстреленное Firebird'ом невозможно в принципе. Если ты заглянешь в таблицу экспорта ib_util.dll, то обнаружишь, что там нет функции освобождения общей памяти, т.к. функция ib_util_malloc используется исключительно для выделения памяти под возвращаемый из UDF функции результат и эта память освобождается уже самим сервером после того, как произошел выход из UDF функции и результат возвращен. Если функции UDF нужна "кучная" память для работы, то она вправе задействовать для этого менеджер памяти самой dll через стандартные Си функции (std::malloc/realloc/free) или операторами C++ (new/delete). Естественно, что все выстреливаемые при этом исключения функция способна обработать самостоятельно в try блоке (сама спровоцировала, сама обработала). ... |
|||
:
Нравится:
Не нравится:
|
|||
22.12.2015, 13:26 |
|
Дополнительная информация при ошибке в UDF
|
|||
---|---|---|---|
#18+
Любые исключения, использующие стандартные механизмы ОС, можно перехватывать и обрабатывать. Это раз. Дельфи использует стандартный механизм и свой собственный код исключения. У MSVC тоже есть свой код для исключений, как и у любого другого компилятора. Это два. Некоторые типы исключений можно обработать гарантированно безопасно и продолжить работу, на остальные непонятно как реагировать. 100500 лет назад было принято решение завершать работу (по возможности - корректным образом) в таких случаях. За все эти 100500 лет не было предложено ничего лучшего с достойной аргументацией (мне тоже это не нравится, но такова селяви). Это три. В самом обработчике исключения контекст (имя БД, юзера и т.п.) - не доступен. Если исключение фатальное (как AV), то exit\abort вызывается из самого обработчика, т.е. нет возможности выше по стеку добавить контекст в сообщение. Поэтому та часть сообщения, которая не зависит от исключения (инф-ция об UDF в нашем случае), формируется заранее (до вызова UDF, на самом деле - при загрузке её метаданных). Можно добавить туда "статическую" инф-цию, не зависящую от контекста конкретного вызова - например имя БД (не уверен, что это будет полезно при анализе причин проблемы). В принципе, можно перед каждым вызовом UDF добавлять туда и имя юзера, и даже параметры - но кому нужны эти накладные расходы, не востребованные в 99.999% случаях ? ... |
|||
:
Нравится:
Не нравится:
|
|||
22.12.2015, 13:31 |
|
Дополнительная информация при ошибке в UDF
|
|||
---|---|---|---|
#18+
CyberMaxС другой стороны, кто-нибудь может сказать, зачем FB вообще падает? При вызове UDF достаточно же сделать try/catch, не? Потому, что обработка исключений собственными средствами C++ может различаться от компилятора к компилятору и совершенно точно отличается от обработки исключений средствами ОС ( SEH ). Для обработки SEH исключения используются блоки __try/__except/__finally, а не try/catch. ... |
|||
:
Нравится:
Не нравится:
|
|||
22.12.2015, 13:38 |
|
Дополнительная информация при ошибке в UDF
|
|||
---|---|---|---|
#18+
CyberMaxDBConstructor, Я тебя умоляю, не пиши в эту тему больше. Извини, дружище! Я пытался, но не смог удержаться. ... |
|||
:
Нравится:
Не нравится:
|
|||
22.12.2015, 13:40 |
|
Дополнительная информация при ошибке в UDF
|
|||
---|---|---|---|
#18+
hvladМожно добавить туда "статическую" инф-цию, не зависящую от контекста конкретного вызова - например имя БД (не уверен, что это будет полезно при анализе причин проблемы). В принципе, можно перед каждым вызовом UDF добавлять туда и имя юзера, и даже параметры - но кому нужны эти накладные расходы, не востребованные в 99.999% случаях ? Именно поэтому я выше и предлагал несколько расширить функционал ib_util.dll, что никак не скажется на legacy, но позволит UDF функции дополнительно дергать из FB информацию для диагностики. ... |
|||
:
Нравится:
Не нравится:
|
|||
22.12.2015, 13:45 |
|
Дополнительная информация при ошибке в UDF
|
|||
---|---|---|---|
#18+
DBConstructorЯ пытался, но не смог удержаться. почти все твои ответы в этом топике не в кассу, за исключением последних двух, и то, должен заметить, что - у дельфей, насколько мне известно, нет для dll штатной возможности писать обработчики типа DLL_PROCESS_DETACH и проч, за исключением секции инициализации, которая будет вызываться при загрузке dll. - даже если по исключению в udf пытаться выгрузить dll и загрузить опять (чтобы освободить память, и т.д.), все равно неизвестно, в какой момент вызвалось исключение, и насколько корректным получится reload. В общем, все рассуждения про менеджеры памяти и проч - вторичны. Кстати, решение "падать" вместе с udf можно считать оправданым, если учитывать, что начинающие пишут в большинстве именно глюкавые функции. Например, люди могут указать не тот тип вызова (stdcall вместо cdecl), при этом функция может работать ГОДАМИ, выдавая еще и в большей части случаев корректный результат :-) ... |
|||
:
Нравится:
Не нравится:
|
|||
22.12.2015, 13:50 |
|
Дополнительная информация при ошибке в UDF
|
|||
---|---|---|---|
#18+
DBConstructorСимонов ДенисDBConstructor, в UDR (FB 3) можно получить любую инфу от сервера без проблем. Но их надо научится готовить. Это немного сложнее чем написать UDF. Обнадёживающе. И другим интересующимся. Небольшой пример на Delphi XE5. Сначала надо скачать вот это https://github.com/asfernandes/fbstuff/archive/master.zip Потом немного изменить текст примера для того, чтобы посмотреть как можно обрабатывать исключения в UDR. НУ и естественно последний снапшот тройки. Код: pascal 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. 87. 88. 89. 90. 91. 92. 93. 94. 95. 96. 97. 98. 99. 100. 101. 102. 103. 104. 105. 106. 107. 108. 109. 110. 111. 112. 113. 114. 115. 116. 117. 118. 119. 120. 121. 122. 123. 124. 125. 126. 127. 128. 129. 130. 131. 132. 133. 134. 135. 136. 137. 138. 139. 140. 141. 142. 143. 144. 145. 146. 147. 148. 149. 150. 151. 152. 153. 154. 155. 156. 157. 158.
Ну и сравнить результаты двух запросов Код: sql 1. 2. 3. 4. 5.
... |
|||
:
Нравится:
Не нравится:
|
|||
22.12.2015, 13:53 |
|
Дополнительная информация при ошибке в UDF
|
|||
---|---|---|---|
#18+
kdv- у дельфей, насколько мне известно, нет для dll штатной возможности писать обработчики типа DLL_PROCESS_DETACH и проч, за исключением секции инициализации, которая будет вызываться при загрузке dll. Сдается мне, что Firebird это делает только при завершении процесса сервера, а посему, выделенная, но не освобожденная DLL'ью память не имеет значения и будет освобождена ОС. kdv- даже если по исключению в udf пытаться выгрузить dll и загрузить опять (чтобы освободить память, и т.д.), все равно неизвестно, в какой момент вызвалось исключение, и насколько корректным получится reload. А вот это, ИМХО, ни к чему. Лучше откатить транзакцию по какому-нибудь PSQL исключению. kdvВ общем, все рассуждения про менеджеры памяти и проч - вторичны. Кстати, решение "падать" вместе с udf можно считать оправданым, если учитывать, что начинающие пишут в большинстве именно глюкавые функции. Спорно... kdvНапример, люди могут указать не тот тип вызова (stdcall вместо cdecl), при этом функция может работать ГОДАМИ, выдавая еще и в большей части случаев корректный результат :-) Кстати, очень ценное замечание! Далеко не во всех статьях о создании UDF для Firebird об этом написано. Сам когда-то прошелся по этим же граблям. :) ... |
|||
:
Нравится:
Не нравится:
|
|||
22.12.2015, 14:03 |
|
Дополнительная информация при ошибке в UDF
|
|||
---|---|---|---|
#18+
Симонов Денис, я правильно понимаю, что в UDR, в качестве API используется vtable заранее известного класса? ... |
|||
:
Нравится:
Не нравится:
|
|||
22.12.2015, 14:30 |
|
Дополнительная информация при ошибке в UDF
|
|||
---|---|---|---|
#18+
DBConstructorkdvНапример, люди могут указать не тот тип вызова (stdcall вместо cdecl), при этом функция может работать ГОДАМИ, выдавая еще и в большей части случаев корректный результат :-) Кстати, очень ценное замечание! Далеко не во всех статьях о создании UDF для Firebird об этом написано. Сам когда-то прошелся по этим же граблям. :) Ценное, только неверное для 32бит =) При cdecl стек очищает вызывающая функция,а при sdcall наоборот. Обязано сдохнуть при первом же вызове. В общем, как я и говорил, и это видно по этому обсуждению, большинство не понимает деталей реализации. Последний пример Симонова для FB3 интересно как себя поведет при AV (где тут главный ломатель? =). И для полноты картины пара деталей -для Linux AV обрабатываются совсем по другому. -есть различия в 32- и 64-бит реализациях ... |
|||
:
Нравится:
Не нравится:
|
|||
22.12.2015, 14:46 |
|
Дополнительная информация при ошибке в UDF
|
|||
---|---|---|---|
#18+
DBConstructor, в качестве API используется vtable. Формируется оно с помощью idl для конкретного языка. ЗимарглПоследний пример Симонова для FB3 интересно как себя поведет при AV (где тут главный ломатель? =). Я хз. Если не ломать собственные указатели status, context, metadata и т.д., то может и нормально, хотя не факт. Тут самое сложно это описать входные и выходные сообщения. В C++ варианте есть пример через буфер, от которого смещение берётся. ... |
|||
:
Нравится:
Не нравится:
|
|||
22.12.2015, 15:03 |
|
Дополнительная информация при ошибке в UDF
|
|||
---|---|---|---|
#18+
Зимаргл Последний пример Симонова для FB3 интересно как себя поведет при AV (где тут главный ломатель? =). И для полноты картины пара деталей -для Linux AV обрабатываются совсем по другому. -есть различия в 32- и 64-бит реализациях Код: pascal 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22.
Код: plaintext 1. 2.
FB не упал ... |
|||
:
Нравится:
Не нравится:
|
|||
22.12.2015, 15:10 |
|
Дополнительная информация при ошибке в UDF
|
|||
---|---|---|---|
#18+
ЗимарглЦенное, только неверное для 32бит =) При cdecl стек очищает вызывающая функция,а при sdcall наоборот. Обязано сдохнуть при первом же вызове. Вот только причем тут различия в реализациях соглашений вызовов, если вызов udf функций Firebird описан именно как cdecl, а не stdcall? Если бы для вызова udf было принято соглашение stdcall и функции в реализации имели бы stdcall, то и в этом случае всё бы работало. Совершенно очевидно, что какое соглашение принято, такое и должно использоваться. ... |
|||
:
Нравится:
Не нравится:
|
|||
22.12.2015, 15:16 |
|
Дополнительная информация при ошибке в UDF
|
|||
---|---|---|---|
#18+
DBConstructor, я не понял твой коммент. Ясное дело, что Зимаргл указывает на разницу, почему и пишет, что при неправильной (не той) декларации "должно сдохнуть при первом вызове". Однако, я писал, что неправильная декларация все же иногда работает. Вот пример, и в этом форуме такое было не раз: http://www.sql.ru/forum/1011000/perenos-udf-s-firebird-2-0-na-2-5?hl=stdcall "Есть udf, которые работали на FB1, FB2." "При переносе на FB2.5 библиотека почему-то перестает работать." еще бывает, что "перестало работать" - при смене ОС (или версии, или 32бит на 64бит), при смене компа, и т.д. Где-то даже разбирали, почему stdcall в udf прикидывается, что работает, и почему иногда не падает, а возвращает мусор. ... |
|||
:
Нравится:
Не нравится:
|
|||
22.12.2015, 15:24 |
|
Дополнительная информация при ошибке в UDF
|
|||
---|---|---|---|
#18+
kdvDBConstructor, я не понял твой коммент. Ясное дело, что Зимаргл указывает на разницу, почему и пишет, что при неправильной (не той) декларации "должно сдохнуть при первом вызове". Однако, я писал, что неправильная декларация все же иногда работает. Вот пример, и в этом форуме такое было не раз: Должно сдохнуть, но не обязано. Всё очень сильно зависит от того, какие операции были последними над регистрами edx:eax, так как cdecl возвращает значение именно через эти регистры (либо в eax адрес на результат в стеке), а stdcall помещает результат внутрь кадра стека вызывающей программы, получив на него адрес последним неявным параметром в кадре переданных параметров. ... |
|||
:
Нравится:
Не нравится:
|
|||
22.12.2015, 16:27 |
|
Дополнительная информация при ошибке в UDF
|
|||
---|---|---|---|
#18+
DBConstructor, а, ну тогда консенсус. ... |
|||
:
Нравится:
Не нравится:
|
|||
22.12.2015, 16:36 |
|
Дополнительная информация при ошибке в UDF
|
|||
---|---|---|---|
#18+
ЗимарглИ для полноты картины пара деталей -для Linux AV обрабатываются совсем по другому. -есть различия в 32- и 64-бит реализациях И для совсем полной полноты компилятор С++ MinGw не использует SEH в исключениях бо коллизии с патентами от M$. ... |
|||
:
Нравится:
Не нравится:
|
|||
24.12.2015, 08:17 |
|
|
start [/forum/topic.php?fid=40&msg=39134354&tid=1562433]: |
0ms |
get settings: |
11ms |
get forum list: |
15ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
32ms |
get topic data: |
11ms |
get forum data: |
3ms |
get page messages: |
62ms |
get tp. blocked users: |
2ms |
others: | 254ms |
total: | 398ms |
0 / 0 |