【问题标题】:printf jokes in multi-threaded application?printf 在多线程应用程序中的笑话?
【发布时间】:2012-08-18 16:42:29
【问题描述】:

下面的代码如何

while(1) {
  client_name_len = sizeof(struct sockaddr_in);
  newsockfd = accept(sockfd, (struct sockaddr *)&client_name, &client_name_len);
  if (newsockfd < 0) {
    perror("ERROR on accept");
    printf("Finished\n");
    close(sockfd);
    exit (EXIT_FAILURE);
  }
  printf("a:");
  pthread_t thread1;
  int *addr = (int*)malloc(sizeof(int));
  *addr = newsockfd;
  pthread_create( &thread1, NULL, &ProcessClient, (void*)addr);
}

产生以下输出:

a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:ERROR on accept: Too many open files
a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:a:Finished

问题是perror("ERROR on accept")printf("Finished\n")printf("a:")在同一个线程中执行,但是输出是混合的。

ProcessClient 不输出任何内容,也不创建任何线程。 sockfd 是一个标准的监听 tcp 套接字。

【问题讨论】:

  • 开什么玩笑?要么是方齐写的,要么是加拿大人写的。 :-)
  • 我假设 OP 的意思是“扼流圈”。但这个问题更有趣的是“笑话”。

标签: c pthreads printf


【解决方案1】:

printf("a:");printf("Finished\n"); 是缓冲 I/O 到标准输出。

perror("ERROR on accept"); 是无缓冲(或立即刷新)的 I/O 到 stderr。

所以在ERROR on accept: Too many open files 之后出现的许多a: 实际上之前是printf(),但是缓冲使它们稍后出现在控制台上。

请参阅https://stackoverflow.com/a/3746795/12711了解解决问题的详细信息和方法。

【讨论】:

    【解决方案2】:

    正如 Michael 所指出的,第一个问题是您使用了两个不同的流(stdout 和 stderr),一个是缓冲的,另一个是非缓冲的。但是,您还将输出分解为多个 stdio 调用,这使其成为非原子的。我建议将perror 替换为:

    printf("ERROR on accept: %s\n", strerror_l(errno));
    

    或将其他 printf 调用切换为在 stderr 上使用 fprintf,以便您在写入哪个流时保持一致。

    然后,为了使其具有原子性,请在函数开头调用 flockfile(f) 并在返回之前调用 funlockfile(f)(其中 f 将替换为您选择使用的 stdoutstderr 中的任何一个)。或者如果你真的还想同时使用它们,你可以同时锁定它们......

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-03-25
      • 1970-01-01
      • 2012-03-26
      • 1970-01-01
      • 1970-01-01
      • 2014-06-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多