pppd popen висит в C

Я запускаю pppd, используя popen в своей программе, чтобы немного упростить получение IP-адреса и имени интерфейса. Мой код отлично работает независимо и является довольно типичной реализацией. Проблема начинается, когда она запускается в полной программе (слишком большой для публикации)... кажется, что цикл довольно долго зависает в строке fgets(). Popen запускается в собственном потоке, который затем управляется на основе вывода.

Код popen/pppd выглядит следующим образом.

int main(void){
    pthread_create(&thread, NULL, pppd, (char *)NULL);
    pthread_join(thread, NULL);

    return 0;
}

void *pppd(char *args){
    char* command = malloc(32);

    sprintf(command, "pppd %s call %s", dev, provider);
    pppd_stream = popen(command, "r");

    if(pppd_stream == NULL){
        pppd_terminated = TRUE;
        return;
    }

    free(command);

    while(fgets(buffer, 128, d->pppd_stream) != NULL){

        //handle_output
    }

}

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

Любые мысли о том, что может быть причиной этого замедления?


person DarkRyuu    schedule 12.08.2012    source источник
comment
Вы проверили, что возвращаемое значение не было NULL?   -  person Flexo    schedule 13.08.2012
comment
Да, извините, это существует в полной версии. Я обновлю сейчас с более точной реализацией.   -  person DarkRyuu    schedule 13.08.2012
comment
Насколько велик ваш процесс и сколько у вас оперативной памяти? Кроме того, вы можете использовать strace -f и следить за дочерними процессами, чтобы увидеть, есть ли системный вызов, который приводит к зависанию pppd. Он зависает при запуске команды pppd из командной строки?   -  person jxh    schedule 13.08.2012
comment
У меня около 128 МБ ОЗУ из 2 ГБ свободно. При запуске pppd из терминала такой проблемы не было, однако я заметил, что сеанс pppd не закрывался даже после попытки kill и killall. После одной перезагрузки командная строка ведет себя так же. strace -f тоже зависает на ioctl(8, TIOCSETD   -  person DarkRyuu    schedule 13.08.2012
comment
Кажется, это проблема с pppd? Моя программа убивала существующий сеанс pppd, если он блокировал устройство, которое я хотел удалить. Я также вручную очищал файл блокировки. Кажется, что PPPD больше не оставляет файл блокировки при выходе, и теперь он работает так, как ожидалось... Теперь я еще больше запутался. Я также не изменил файл опций pppd, чтобы он не блокировался.   -  person DarkRyuu    schedule 13.08.2012


Ответы (1)


Убедитесь, что ваша команда является строкой с завершающим нулем:

#define COMMAND_BUFFER_SIZE    256   /* Modify this if you need */

snprintf(command, COMMAND_BUFFER_SIZE, "pppd %s call %s", dev, provider);
command[COMMAND_BUFFER_SIZE - 1] = '\0';
pppd_stream = popen(command, "r");

ИЗМЕНИТЬ:

Проверьте свой fgets:

while(fgets(buffer, 128, d->pppd_stream) != NULL){

Вы можете захотеть это:

while(fgets(buffer, 128, pppd_stream) != NULL){
person TOC    schedule 12.08.2012
comment
Спасибо, в моей программе я фактически установил массив в '\ 0', прежде чем использовать его. Что должно иметь тот же эффект, мне, вероятно, следует перестать так сильно обрезать свой код для загрузки. - person DarkRyuu; 13.08.2012
comment
snprintf всегда заканчивается нулем, если только аргумент размера не равен нулю, и в этом случае он ничего не записывает. - person R.. GitHub STOP HELPING ICE; 13.08.2012