【问题标题】:Print and read from xterm in a multithreaded C program using cat, tee and fifos使用 cat、tee 和 fifos 在多线程 C 程序中从 xterm 打印和读取
【发布时间】:2016-05-09 07:07:28
【问题描述】:

我正在尝试在我的 C 程序中创建一个聊天界面。 该程序使用两个fifo与同时运行命令cat fifo_outtee fifo_in > /dev/null的分叉xterm进行通信。 然后打开一个线程来读取 *fifo_in 中的输入 感谢tee,来自终端,同时另一个线程在 fifo_out 中打印消息,并在 xterm 中显示内容。

一切似乎都运行良好...除了在终端中写入一些文本时打印了一条消息,将输入的文本分成两部分。这会导致段错误!

你知道为什么会这样吗?

这是一个最小的例子:

int open_terminal(pid_t *pid, int *pipe)
{
  mkfifo("fifo_in", 0600);
  mkfifo("fifo_out", 0600); 
  pid_t p = fork();
  int fd_in, fd_out;
  switch (p) {
    case -1:
      return -1;
    case 0:
        execlp("xterm", "xterm", "-e", "cat fifo_out & tee fifo_in > /dev/null", NULL);
        exit(EXIT_FAILURE);
        break;
    default:
        if ((fd_in = open("fifo_in", O_RDONLY)) == - 1)
          return -1;
        if ((fd_out = open("fifo_out", O_WRONLY)) == - 1)
          return -1;
        *pid = p;
        pipe[0] = fd_in; pipe[1] = fd_out;
        return 0;
  }
  return -1;
}


void *message_thread(void *args)
{
  int *fd_out = (int *)args;
  while (1) {
    dprintf(*fd_out, "You're awesome!\n");
    sleep(5);
  }
}


void *input_thread(void *args)
{
  int *fd_in = (int *)args;
  FILE *f = fdopen(*fd_in, "r");
  while (1) {
    size_t n;
    char *line;
    getline(&line, &n, f);
    printf("Read: %s", line);
    free(line);
    if(strcmp(line, "exit\n") == 0)
      return NULL;
  }
}


int main(int argc, char *argv[])
{
  pid_t pid;
  int pipe[2];
  if (open_terminal(&pid, pipe) == -1) {
    printf("Can't open terminal.\n");
    return 1;
  }
  pthread_t mt, it;
  pthread_create(&mt, NULL, message_thread, &pipe[1]);
  pthread_create(&it, NULL, input_thread, &pipe[0]);

  pthread_join(it, NULL);

  return 0;
}

要重现我的情况,运行程序输入一些文本,等到在你的文本之后打印一些文本,然后再次输入并输入。

【问题讨论】:

  • 您可能还想查看unlink 命令以在退出程序时清理fifos。如果有任何区别,您可能还想从getline 的输入中修剪尾随'\n'。由于getline 返回读取的字符数(包括'\n'),您可以简单地使用返回(例如nchr = getline (... 然后line[--nchr] = 0; 删除'\n'。然后您不需要看起来很奇怪的测试喜欢strcmp(line, "exit\n")

标签: c multithreading cat fifo tee


【解决方案1】:

来自input_thread 函数:

free(line);
if(strcmp(line, "exit\n") == 0)

首先释放line 分配和指向的内存,然后立即使用该内存。这会导致未定义的行为

这还不是全部,因为你将一个未初始化的指针和大小传递给getline 函数,它实际上不会分配内存,因为未初始化的局部变量有一个 indeterminate 值(它看起来是随机的而且不太可能为零或NULL)。将变量显式初始化为零和NULLgetline 函数将分配所需的内存。将未初始化的本地(非静态)变量用于除初始化之外的任何其他操作也会导致未定义的行为。

这可能是来自getline 写入一些看似随机的内存的未定义行为导致崩溃。

【讨论】:

  • 糟糕,free 不在正确的位置,我没有看到,但实际程序中并非如此。真正的原因是另一个,未初始化的size_t。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-08
  • 2019-03-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多