Firebird API клиент на C++ "падает" на isc_dettach

IBX, FIBPlus, UIB, ADO, .Net и прочее-прочее-прочее, в общем все, что относится к созданию приложений, работающих с InterBase, Firebird и Yaffil - клиент-серверных, трехзвенных, консольных и т.п.

Модератор: kdv

Ответить
Saltaev
Сообщения: 6
Зарегистрирован: 25 апр 2006, 13:24

Firebird API клиент на C++ "падает" на isc_dettach

Сообщение Saltaev » 25 апр 2006, 14:39

/*
Выполнение этого кода неминуемо заканчивается "крушением" программы. Почему?
Вызов isc_attach_database из main, затем isc_detach_database из finisher в контексте main выполняется успешно, а вот на второй итерации функция finisher выполняется за пределами контекста main - и isc_detach_database в ней вызывает "крушение" программы
Очевидно, Firebird какие-то данные размещает в стеке, стек разрушается...

Информация о версиях:
  • gcc version 3.4.2 20041017 (Red Hat 3.4.2-6.fc3)
    Firebird TCP/IP server version LI-V1.5.2.4731 Firebird 1.5
    Kernel 2.6.9-1.667 on an i686
04.10.2006
*/[/color]


#include <ibase.h>
#include <stdio.h>
#include <stdlib.h>


isc_db_handle db = NULL;

void finisher(void){
  • ISC_STATUS res = 0;
    ISC_STATUS_ARRAY status_vector;
    res = isc_detach_database(status_vector, &db); //:?:
    printf("isc_detach_database: %ld \n", res);
    return;
}

int main (int argc, char **argv){
  • atexit(finisher);

    ISC_STATUS res = 0;
    ISC_STATUS_ARRAY status_vector;

    for (int i = 1; i <= 2; i++){
    • res = isc_attach_database(status_vector, 8, "employee", &db, 32, "\x01\x1C\x06SYSDBA\x1D\x08masterke\x30\x0Bunicode_fss");
      printf("isc_attach_database: %ld \n", res);
      if (i != 2){
      finisher();
      }
    }
    printf("main_finished\n");
}

v6y
Сообщения: 78
Зарегистрирован: 12 мар 2005, 17:45

Re: Firebird API клиент на C++ "падает" на isc_det

Сообщение v6y » 25 апр 2006, 18:06

На FB 2.0 RC1 тоже "падает". Причем анализ корки говорит что падение происходит в

Код: Выделить всё

0  0xb7f0ef7c in KEYWORD_getTokens () from /usr/lib/libfbembed.so.2
Но кто здесь виноват - atexit или fb - утверждать не берусь, а копаться недосуг.

P.S.
Если строкой коннекта указать

Код: Выделить всё

res = isc_attach_database(status_vector, 0, "localhost:employee", &db, 32, "\x01\x1C\x06SYSDBA\x1D\x08masterke\x30\x0Bunicode_fss");
То все отрабатывает нормально
P.P.S. Оригинальный способ заполнения dpb :D

hvlad
Разработчик Firebird
Сообщения: 1244
Зарегистрирован: 21 мар 2005, 10:48

Re: Firebird API клиент на C++ "падает" на isc_det

Сообщение hvlad » 25 апр 2006, 18:55

v6y писал(а):На FB 2.0 RC1 тоже "падает". Причем анализ корки говорит что падение происходит в

Код: Выделить всё

0  0xb7f0ef7c in KEYWORD_getTokens () from /usr/lib/libfbembed.so.2
Но кто здесь виноват - atexit или fb - утверждать не берусь, а копаться недосуг.
Она возращает static const переменную. Похоже, что в момент вызова atexit, сегмент данных уже разрушен.
Подробнее я бы искал в доке на atexit в реализации данного компилятора.
MSVC писал(а):No global static objects initialized prior to the call to atexit are destroyed prior to execution of the exit-processing function
Честно говоря, не вижу смысла делать detach из atexit ...
v6y писал(а):P.S.
Если строкой коннекта указать

Код: Выделить всё

res = isc_attach_database(status_vector, 0, "localhost:employee", &db, 32, "\x01\x1C\x06SYSDBA\x1D\x08masterke\x30\x0Bunicode_fss");
То все отрабатывает нормально
Ибо на линуксе локальное подключение - это сервер в твоём процессе, а localhost - сервер в своём процессе

v6y
Сообщения: 78
Зарегистрирован: 12 мар 2005, 17:45

Re: Firebird API клиент на C++ "падает" на isc_det

Сообщение v6y » 26 апр 2006, 08:21

hvlad писал(а): Похоже, что в момент вызова atexit, сегмент данных уже разрушен.
Дело в том, что если подключать библиотеку fbclient, то все работает нормально, а если fbembed, то имеет место "Segmentation fault".
Подробнее я бы искал в доке на atexit в реализации данного компилятора.
MSVC писал(а):No global static objects initialized prior to the call to atexit are destroyed prior to execution of the exit-processing function
Я все таки не уверен на все 100 что это именно atexit во всем виноват
Честно говоря, не вижу смысла делать detach из atexit ...
Дело не в смысле, а в том что имеет место поведение, отличное от ожидаемого. Не подумай, что это наезд, но я считаю, что если есть какие-то аномалии, то их желательно устранить или хотя бы установить точную причину возникновения. Хотя... Если ты абсолютно уверен, что дело исключительно в atexit, то пусть так оно и будет

Saltaev
Сообщения: 6
Зарегистрирован: 25 апр 2006, 13:24

Re: Firebird API клиент на C++ "падает" на isc_det

Сообщение Saltaev » 26 апр 2006, 09:40

v6y писал(а):P.P.S. Оригинальный способ заполнения dpb :D
Да, пожалуй. Вначале я использовал isc_expand_dpb, потом она мне разонравилась, написал свою функцию, которую использую также при формировании spb в isc_service_attach и isc_service_start. Выкладывать не стал - хотел выложить компактный работающий пример.
v6y писал(а):Но кто здесь виноват - atexit или fb - утверждать не берусь, а копаться недосуг.
Да, ничего не поделаешь. Кстати, писал об этом preeves@ibphoenix.com. То ли я плохо по-английски пишу, то ли не по адресу обратился - ответ какой-то ни рыба ни мясо.
hvlad писал(а):Честно говоря, не вижу смысла делать detach из atexit ...
Со временем моя программа разраслась, появился графический интерфейс и т. д. Отключение от БД происходит задолго до atexit и проблемы как таковой не стало. Однако поделиться ей с коллегами считаю необходимо.

hvlad
Разработчик Firebird
Сообщения: 1244
Зарегистрирован: 21 мар 2005, 10:48

Re: Firebird API клиент на C++ "падает" на isc_det

Сообщение hvlad » 26 апр 2006, 13:20

v6y писал(а):
hvlad писал(а): Похоже, что в момент вызова atexit, сегмент данных уже разрушен.
Дело в том, что если подключать библиотеку fbclient, то все работает нормально, а если fbembed, то имеет место "Segmentation fault".
Потому, что та самая переменная живёт в fbembed, т.е. в сервере.
v6y писал(а):Я все таки не уверен на все 100 что это именно atexit во всем виноват
Честно говоря, не вижу смысла делать detach из atexit ...
Дело не в смысле, а в том что имеет место поведение, отличное от ожидаемого. Не подумай, что это наезд, но я считаю, что если есть какие-то аномалии, то их желательно устранить или хотя бы установить точную причину возникновения. Хотя... Если ты абсолютно уверен, что дело исключительно в atexit, то пусть так оно и будет
Я другого вывода из имеющейся информации сделать не могу.
Похоже, что к моменту вызова atexit библиотека уже выгружена из памяти.
Я этого проверить не могу, да и не хочу - есть чем заниматься

hvlad
Разработчик Firebird
Сообщения: 1244
Зарегистрирован: 21 мар 2005, 10:48

Re: Firebird API клиент на C++ "падает" на isc_det

Сообщение hvlad » 26 апр 2006, 13:24

Saltaev писал(а): Кстати, писал об этом preeves@ibphoenix.com
Если уж сильно хочется разобраться, пиши в fb-devel или в баг-трекер

Dimitry Sibiryakov
Заслуженный разработчик
Сообщения: 1436
Зарегистрирован: 15 сен 2005, 09:05

Сообщение Dimitry Sibiryakov » 26 апр 2006, 14:17

Лично я вообще не вижу смысла ставить detach в atexit. Если приложение завершается некорректно то коннект упадет сам собой. Баги надо править а не соломку подстилать.

v6y
Сообщения: 78
Зарегистрирован: 12 мар 2005, 17:45

Сообщение v6y » 26 апр 2006, 15:58

Dimitry Sibiryakov писал(а):Лично я вообще не вижу смысла ставить detach в atexit. Если приложение завершается некорректно то коннект упадет сам собой. Баги надо править а не соломку подстилать.
Ребята, ну вы же профи... Имеет место "неправильное" поведение. Хорошо если его причиной действительно является реализация atexit... А если нет? А если это действительно баг FB и он может привести к сбою в какой-нибудь другой ситуации? Вот в этом то вам как профи в первую очередь и надо видеть некий смысл, ИМХО. Ну а если считаете этот момент малозначительным - да и нехай с ним - лично мне он тоже жить не мешает.

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 26 апр 2006, 16:13

Вызов isc_attach_database из main, затем isc_detach_database из finisher в контексте main выполняется успешно, а вот на второй итерации функция finisher выполняется за пределами контекста main - и isc_detach_database в ней вызывает "крушение" программы
Очевидно, Firebird какие-то данные размещает в стеке, стек разрушается...
я в сях не профи, но я тебе скажу, что такой метод закрытия коннекта весьма крив. Когда там этот atexit вызывается, и в каком контексте - фиг его знает. О чем тебе Влад сразу и сказал.
Ты можешь поступить по другому - запихнуть какую-нибудь кривую переменную в isc_detach и если функция "упадет", то клевать разработчиков, что у них там криво параметры проверяются.
А так, нет смысла - ну падает, ну и что? Тем более что твой вариант сильно напоминает методу, когда getmem делается в одном месте, а freemem хрен знает где и из непонятного контекста... Причем, как ты сам сказал, ДВА раза...

v6y
Сообщения: 78
Зарегистрирован: 12 мар 2005, 17:45

Сообщение v6y » 26 апр 2006, 17:45

Вобщем не удержался и разобрался :D Тут ни atexit, ни FB не виноваты.
Если народу интересно, то расскажу в чем тут на самом деле дело.

P.S. На разбор около 5 минут ушло, однако :D

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 26 апр 2006, 17:50

как бы, принято делиться найденным решением проблемы, каким бы оно ни было... :)

v6y
Сообщения: 78
Зарегистрирован: 12 мар 2005, 17:45

Сообщение v6y » 26 апр 2006, 18:26

kdv писал(а):как бы, принято делиться найденным решением проблемы, каким бы оно ни было... :)
Дело в том, что при вызове isc_attach_databse вызывается atexit(gds__cleanup). Поскольку при выходе из программы функции, зарегистрированные atexit-ом, вызваются в обратном порядке, то данном случае вначале вызовется gds__cleanup и лишь затем finisher.
Таким образом к моменту вызова finisher, gds__cleanup уже очистил соответсвующую область памяти и автор самым естественным образом получил SIGSEGV. Поэтому, если в указанном примере переместить atexit(finisher) за цикл, то все отработает нормально, поскольку в данном случае вначале выполнится finisher и лишь затем gds__cleanup. Так что Влад прав, предположив, что данные к моменту вызова finisher разрушенны и что дело тут в реализации atexit, хоть и основаны его предположения на несклолько других посылках ;-)

P.S. Что бы это увидеть, достаточно было закомпилить данный пример с отладочной информацией, прилинковать libfbembed.so.2.0.0.debug и запустить через отладчик :-)

Ответить