Модераторы: xvr
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> проблема с подключаемым модулем, форкнутый процесс убивает сокет 
V
    Опции темы
fish9370
Дата 26.3.2013, 11:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 663
Регистрация: 15.4.2007
Где: Москва

Репутация: 2
Всего: 1



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

и здесь у меня появилась проблема: почему-то при автозапуске, если в модуле открывается сокет, этот сокет оказывается кривым, переодически функция recvfrom возвращает сообщение об ошибке (Bad file descriptor).
Все это происходит именно при форке, при запуске проги в режиме no-fork все работает как положено..

функция демонизации:
Код

void server_way()
{
        int i, f, ppid;
        char str[10];
        if (getppid() == 1)
                return;

        if (!flags.console) {
                ppid = fork();
                if (ppid < 0) {
                        bs_verbose(LOG_ERROR, "fork error");
                        exit(1);
                }
                if (ppid > 0)
                        exit(0);

                setsid();

                /* we don't need close any descriptors */
                /* for (i = getdtablesize(); i >= 0; --i) {
                        close(i);
                }*/

                i = open("/dev/null", O_RDWR);
                dup(i);
                dup(i);
        }

        umask(027);
        chdir(config_global.bsrundir);

        f = open("basys.pid", O_RDWR | O_CREAT, 0640);
        if (f < 0) {
                bs_verbosef(lf, LOG_VERBOSE, "Can not open 'basys.pid' file\n");
                fflush(lf);
                exit(1);
        }

        if (lockf(f, F_TLOCK, 0) < 0)
                exit(0);

        sprintf(str, "%d\n", getpid());
        write(f, str, strlen(str));

        signal(SIGCHLD,SIG_IGN);
        signal(SIGTSTP,SIG_IGN); /* ignore tty signals */
        signal(SIGTTOU,SIG_IGN);
        signal(SIGTTIN,SIG_IGN);

        signal(SIGHUP, signal_handler); /* catch hangup signal */
        signal(SIGTERM, signal_handler); /* catch kill signal */

        makesocket();

        for (i = 0; i < MAX_CONSOLES; i++)
                consoles[i].fd = -1;

        tv_startuptime = bs_tvnow();
        bs_verbosef(lf, LOG_VERBOSE, ">> server started\n");
        fflush(lf);

        while (!process_done) {

                bs_verbosef(lf, LOG_VERBOSE, "wait new connection\n");
                fflush(lf);

                int s;
                if ((s = accept(sock, (struct sockaddr *) &address, &addrlen)) < 0)
                        continue;

                for (i = 0; i < MAX_CONSOLES; i++) {
                        if (consoles[i].fd < 0) {
                                consoles[i].fd = s;
                                pthread_create(&consoles[i].tid, NULL, messenger, &consoles[i]);
                                pthread_detach(consoles[i].tid);
                                break;
                        }
                }

                if (i >= MAX_CONSOLES)
                        bs_verbosef(lf, LOG_VERBOSE, "unable to connect, max connections\n");

                usleep(100);
        }

        struct bs_cli_entry *current;
        while ((current = BS_LIST_REMOVE_HEAD(&commands, list)))
                free(current);

        struct bs_module_entry *mod;
        while ((mod = BS_LIST_REMOVE_HEAD(&modules, list))) {
                module_unload(mod->handle);
                free(mod);
        }

        close(f);
        fclose(lf);
}



еще несколько замечаний: 
прога ведет лог, и вот что в этом логе странного:

Код

tdns.c:load_module:975 loading config '/etc/basys/tdns.conf'
tdns.c:init_threads:260 count: '1000', size: '8'
tdns.c:handler_start:763 Starting listening connection
[color=red]tdns.c:handler_stop:809 wait for thread ab0cc700[/color]
src/basys.c:server_way:985 >> server started
src/basys.c:server_way:990 wait new connection


где, tdns.c - это код модуля, basys.c - это код ядра
при загрузке модуля, как и положено в unix, вызывается функция с символом _init (попросту говоря конструктор), который и вызывает функцию handler_start() - мы ее наблюдаем в логе
но дальше мы видим вызов функции handler_stop(), которая вызывается из деструктора (выделил красным), но я ее не вызывал, при этом для модуля функцию dlclose  я тоже не вызывал

есть у кого-то хотябы предположения, что происходит?



--------------------
undefined
PM MAIL WWW ICQ   Вверх
xvr
Дата 26.3.2013, 11:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 20
Всего: 223



Цитата(fish9370 @  26.3.2013,  11:07 Найти цитируемый пост)
есть у кого-то хотябы предположения, что происходит?

Похоже отрабатывают деструкторы в родительском процессе, который завершили в процессе демонизации (строка 15)
Распечатайте в логе pid процесса

PM MAIL   Вверх
fish9370
Дата 26.3.2013, 12:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 663
Регистрация: 15.4.2007
Где: Москва

Репутация: 2
Всего: 1



спасибо xvr, что проявил интерес к проблеме, 

я не совсем понял, что за пид нужен, напечатал так:

Код

[root@a3 bs]# basys
src/basys.c:server_way:941 ppid: 12821


Код

tdns.c:load_module:975 loading config '/etc/basys/tdns.conf'
tdns.c:init_threads:260 count: '1000', size: '8'
tdns.c:handler_start:763 Starting listening connection
tdns.c:handler_stop:809 wait for thread a4ae4700
src/basys.c:server_way:945 ppid: 0
src/basys.c:server_way:991 >> server started
src/basys.c:server_way:996 wait new connection


Добавлено через 3 минуты
Цитата(xvr @  26.3.2013,  11:53 Найти цитируемый пост)
Похоже отрабатывают деструкторы в родительском процессе, который завершили в процессе демонизации (строка 15)


вроде как открытые дескрипторы (то же касается и дескрипторов открытых либ?) передаются дочернему процессу и не закрываются, пока есть хоть один владелец?


--------------------
undefined
PM MAIL WWW ICQ   Вверх
fish9370
Дата 26.3.2013, 12:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 663
Регистрация: 15.4.2007
Где: Москва

Репутация: 2
Всего: 1



сделал так:

Код

if (ppid > 0) {
                        bs_verbose(LOG_DEBUG, "ppid: %d\n", ppid);
                        while(1);
                        exit(0);
                }



и о чудо, сокет жив и работает, пока родительский процесс живет,
xvr ты оказался прав..

но как выкручиваться из этой ситуации?


--------------------
undefined
PM MAIL WWW ICQ   Вверх
fish9370
Дата 26.3.2013, 14:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 663
Регистрация: 15.4.2007
Где: Москва

Репутация: 2
Всего: 1



решил проблему, отложенной загрузкой модулей (после форка)

спасибо xvr, очень ценный ответ +1


--------------------
undefined
PM MAIL WWW ICQ   Вверх
xvr
Дата 27.3.2013, 07:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 20
Всего: 223



Цитата(fish9370 @  26.3.2013,  12:12 Найти цитируемый пост)
вроде как открытые дескрипторы (то же касается и дескрипторов открытых либ?) передаются дочернему процессу и не закрываются, пока есть хоть один владелец? 

Дескрипторы либ на самом деле не дескрипторы - они организуются на уровне пользователя динамическим линкером, и как они ведут себя при fork'е я лично не в курсе.
По поводу сокетов - да, дескрипторы наследуются. Но для убиения сокета не обязательно закрывать его дескриптор, достаточно сделать shutdown на дескриптор (любой) и сокет помрет, не взирая на наличие любого количества других открытых дескрипторов  smile 

PM MAIL   Вверх
gormih
Дата 28.3.2013, 16:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 9
Регистрация: 18.7.2007

Репутация: 1
Всего: 1



Цитата(xvr @  27.3.2013,  07:21 Найти цитируемый пост)
Дескрипторы либ на самом деле не дескрипторы - они организуются на уровне пользователя динамическим линкером, и как они ведут себя при fork'е я лично не в курсе.
По поводу сокетов - да, дескрипторы наследуются. Но для убиения сокета не обязательно закрывать его дескриптор, достаточно сделать shutdown на дескриптор (любой) и сокет помрет, не взирая на наличие любого количества других открытых дескрипторов   

При fork любой процесс, у которого  пропадают все  процессы - родители попадает под базовый системный процесс init, который его успешно убивает (по задумке) smile. 
А что с ним делать - другой вопрос... В вашей либе судя по всему формируется системный вызов exit(), который или превращает процесс в зомби, если на него не отреагировать, или дает родительскому процессу ( в.т.ч. init ) возможность перезапустить/убить процесс. Информация к размышлению так сказать smile


Это сообщение отредактировал(а) gormih - 28.3.2013, 16:46
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С/С++: Программирование под Unix/Linux"
xvr
  • Проставьте несколько ключевых слов темы, чтобы её можно было легче найти.
  • Не забывайте пользоваться кнопкой "Код".
  • Вопросы мобильной разработки тут
  • Телепатов на форуме нет! Задавайте чёткий, конкретный и полный вопрос. Указывайте полностью ошибки компилятора и компоновщика.
  • Новое сообщение должно иметь прямое отношение к разделу форума. Флуд, флейм, оффтопик запрещены.
  • Категорически запрещается обсуждение вареза, "кряков", взлома программ и т.д.

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, xvr.

 
 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Программирование под Unix/Linux | Следующая тема »


 




[ Время генерации скрипта: 0.0487 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.