системный вызов popen () зависает в HP-Ux 11.11 - PullRequest
0 голосов
/ 26 апреля 2011

У меня есть программа, которая вычисляет значение «Всего очередей принтера», используя «/ usr / bin / lpstat» через системный вызов popen ().

{
    int                     n=0;
    FILE                    *fp=NULL;

    printf("Before popen()");
    fp = popen("/usr/bin/lpstat -o | grep '^[^ ]*-[0-9]*[ \t]' | wc -l", "r");
    printf("After popen()");

    if (fp == NULL)
    {
            printf("Failed to start lpstat - %s", strerror(errno));
            return -1;
    }

    printf("Before fscanf");
    fscanf(fp, "%d", &n);
    printf("After fscanf");

    printf("Before pclose()");
    pclose(fp);
    printf("After pclose()");

    printf("Value=%d",n);
    printf("=== END ===");
    return 0;
}

Примечание. В командной строке команда / usr / bin / lpstat некоторое время зависает, поскольку в сети доступно много принтеров.

Проблема здесь в том, что выполнение зависает при системном вызове popen (), где, как и следовало ожидать, оно зависает при fscanf (), которая читает выходные данные из потока файлов fp.

Если кто-нибудь может рассказать мне о причинах зависания системного вызова popen (), это поможет мне изменить программу, чтобы она работала в соответствии с моими требованиями.

Спасибо, что нашли время на прочтение этого поста и ваши усилия.

Ответы [ 2 ]

0 голосов
/ 26 апреля 2011

Звучит так, как будто popen может зависать, пока lpstat пытается получить информацию с удаленных принтеров.Существует достаточно много дискуссий по этой конкретной проблеме.Посмотрите на эту ветку, и особенно те, которые связаны с этим.

0 голосов
/ 26 апреля 2011

То, что люди ожидают , не всегда имеет основание в реальности: -)

Команда, которую вы выполняете, на самом деле не генерирует никакого вывода, пока не будет завершена.Вот почему он, кажется, зависает в popen, а не fscanf.

. Есть две возможные причины для того, что сразу приходит на ум.

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

Дальний больше скорее всего - влияние трубы.Одна вещь, которую я заметил, это то, что некоторые фильтры (например, grep) объединяют свои линии для эффективности.Таким образом, хотя popen сам может извергать свои строки немедленно (ну, в любом случае, пока он не доберется до бита задержки), тот факт, что grep удерживает строки до тех пор, пока не получит достаточно большой блок, может вызыватьdelay.

Фактически, это почти наверняка pipe-through-wc, который не может генерировать любой вывод, пока все строки не будут получены от lpstat (вы не можете выяснить, сколько там строкдо тех пор, пока не будут получены все строки).Таким образом, даже если popen только что дождался появления первого символа , казалось бы, именно в этом месте зависание.

Было бы просто проверить это, простоудалите бит pipe-through-grep-and-wc и посмотрите, что произойдет.


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

Я бы начал с изменения их в форму:

printf ("message here\n"); fflush (stdout); fsync (fileno (stdout));

, чтобы убедиться, что они очищены полностью , прежде чем продолжить.Я бы не хотел, чтобы это было простым неправильным пониманием проблемы буферизации: -)

...