llseek возвращает ESPIPE при вызове zcat all.tgz | ./cycletee - PullRequest
0 голосов
/ 20 декабря 2011

Я изменил GNU tee на cycletee Исходный код (Вы можете загрузить двоичный файл с https://github.com/vls/cycletee/tree/master/bin)

Что это может быть объяснено на следующем примере:

seq 10 | cycletee 1.txt 2.txt 3.txt
cat 1.txt // prints 1, 4, 7, 10
cat 2.txt // prints 2, 5, 8
cat 3.txt // prints 3, 6, 9

Тогда есть all.tgz (см. Приложение для построения сценария)

all.tgz имеет три текстовых файла и всего 9000000 строк.

Все хорошо. Например:

seq 10000000 | ./cycletee 1.txt 2.txt 3.txt

zcat all.tgz | tee 1.txt > /dev/null

zcat all.tgz | tail // got 9000000 at the last line

, кроме вызова:

zcat all.tgz | ./cycletee 1.txt 2.txt 3.txt

, когда он читает строку № 3000000, он выходит.

strace it Я получил это сообщение и оно вышло:

_llseek(2, 0, 0xffbec3d0, SEEK_CUR)     = -1 ESPIPE (Illegal seek)

Вопрос

  • Каждый может указать на проблемумой исходный код?

  • Любая техника отладки для выяснения проблемы будет оценена. Я не знаю, как использовать gdb в этой ситуации.

Приложение

  • all.tgz может быть построено на этом Python sciprt https://gist.github.com/1500742

  • Среда: Ubuntu 10.0432 бита, CentOS 5.4 64 бита

Ответы [ 2 ]

1 голос
/ 20 декабря 2011

Из источника:

read:
    buffer[0] = '\0';
    ptr = fgets(buffer, (int) sizeof buffer, stdin);
    if(NULL == ptr) {
        if(ferror(stdin)) {
            error (0, errno, "%s", _("standard input"));
            ok = false;
        }
        flag_break = true;
        break;
    }
    bytes_read = strlen(buffer);


      if (bytes_read < 0 && errno == EINTR)
      {
          flag_continue = true;
          backup_i = i;
          break;
      }
      if (bytes_read <= 0) {
          flag_break = true;
          break;
      }

    if (descriptors[0]
            && fwrite(buffer, bytes_read, 1, descriptors[0]) != 1)
            {
                error (0, errno, "%s", files[0]);
                descriptors[0] = NULL;
                ok = false;
            }
 ...

Я не думаю, что это будет работать на двоичном входе (вход, который содержит NUL).[Учитывая подписанность bytes_read, у меня есть сильное подозрение, что fread () был заменен на fgets () + strlen ();] Это может или не может быть причиной ошибки ТРУБЫ, но это выглядит очень неправильно.

1 голос
/ 20 декабря 2011

Вы не можете вызвать llseek или ftell для канала или сокета, они не являются файлами для поиска.

Вы можете использовать отладчик, например gdb (его действительно стоит изучить;и GDB очень хорошо задокументировано ), и, например, поставьте точку останова на _llseek

Вы также можете использовать strace или ltrace

...