llseek 调用 zcat all.tgz 时返回 ESPIPE | ./自行车运动员

发布于 2024-12-21 23:16:37 字数 1440 浏览 0 评论 0 原文

我将 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< /code> (构建脚本参见附录

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

当它读取到 No.3000000 行时,它退出。

strace it 我收到这条消息,它退出了:

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

问题

  • 任何人都可以指出我的源代码有问题吗?

  • 任何解决问题的调试技术都将受到赞赏。我不知道在这种情况下如何使用 gdb

附录

I modified GNU tee to cycletee Source Code (You can download the binary from https://github.com/vls/cycletee/tree/master/bin)

What it does can be explained by the following example:

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

Then there is a all.tgz (See Appendix for building script)

all.tgz has three text file and totally 9000000 lines.

Everything is fine. Like:

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

except calling:

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

when it reads the No.3000000 line, it exits.

strace it I got this message and it exited:

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

Question

  • Anyone can point out the problem of my source code?

  • Any debugging technique to figure out the problem will be appreciated. I don't know how to use gdb in this situation.

Appendix

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

暮色兮凉城 2024-12-28 23:16:37

从来源来看:

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() 取代; ] 这可能是也可能不是 PIPE 错误的原因,但它看起来非常错误。

From the source:

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;
            }
 ...

I don't think this will work on binary input (input that contains NULs).
[ Given the signedness of bytes_read, I have the strong suspicion that fread() has been replaced by fgets() + strlen(); ] This may or may not be the cause of the PIPE error, but it looks very wrong.

伤痕我心 2024-12-28 23:16:37

您不能在管道或套接字上调用 llseekftell,它们不是可查找的文件。

您可以使用像 gdb 这样的调试器(确实值得学习使用它;并且 GDB 非常好记录),例如在 _llseek 上放置断点

您也可以使用 straceltrace

You cannot call llseek or ftell on a pipe or socket, they are not seekable files.

You could use a debugger like gdb (it is really worth learning to use it; and GDB is very well documented), and e.g. put a breakpoint on _llseek

You could also use strace or ltrace

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文