【问题标题】:Impact of socket descriptor closed twice bug in multithreaded program多线程程序中套接字描述符关闭两次错误的影响
【发布时间】:2021-03-22 19:23:38
【问题描述】:
fd = open("file", O_RDONLY);
if (fd < 0) exit(1);

while((res = read(fd, buf, sizeof(buf)))){
if (res < 0){
close(fd);
fprintf(stderr, "Read error!\n");
break;
} else {
printf("Read %zd bytes\n", res);
}
}
close (fd);

在单线程程序中,这是一个明显的错误:'fd' 被关闭了两次。这个错误对多线程程序有什么影响?

【问题讨论】:

  • 与单线程程序没有什么不同:第二次 close() 调用将失败...
  • @prog-fh 如果另一个线程在两个close 调用之间打开一个文件或套接字并获得相同的描述符怎么办?
  • @DavidSchwartz 如果它以任何方式打开相同的资源(使用dup()),那么关闭调用将使第一个文件描述符不可用但相同的资源其他文件描述符仍可访问。但是这两个关闭调用不适用于同一个文件描述符。啊...好吧,我明白了,您是在谈论竞争条件...好吧,任何事情都可能发生,那么为什么要针对这个问题呢?
  • @prog-fh 对。此代码可能是与 any 其他 any 其他线程可能正在运行的其他代码的竞争条件的一半。谁知道那个比赛条件会做什么?

标签: filesystems c multithreading


【解决方案1】:

一方面,关闭一个已经关闭的 fd 只会让你的第二个close() 返回EBADF(fd 不是一个有效的打开文件描述符)。这是无害的。

另一方面,在多线程程序中,没有什么可以保证 fd 不会被重用,例如在对close() 的两次调用之间,另一个线程正在调用open()。在这种情况下,您会意外关闭最近打开的文件,这是有害的。

【讨论】:

    【解决方案2】:

    它可以是任何东西。没有可靠的方法来预测多线程程序中“污染”共享资源的影响。

    最明显的问题是,您可能会在第一次关闭之后但在第二次关闭之前关闭另一个线程出于某些重要目的而打开的套接字。但是,如果不了解代码,您就无法预测某些代码在这种情况下会做什么。

    仅作为一个示例,您可能会过早终止与远程服务器的连接,导致服务器处理部分请求而不是完整请求。如果不了解正在使用的协议,就无法知道该部分请求可能会做什么。

    这是一个更糟糕的情况:

    1. 此线程关闭描述符 4。
    2. 日志记录线程打开一个本地文件并获取描述符 4。
    3. 此线程再次关闭描述符 4。 (错误。)
    4. 另一个线程打开与不受信任服务器的套接字连接并获取描述符 4。
    5. 日志线程再次运行并将敏感信息写入描述符 4。

    哎呀。我们刚刚向一个随机远程连接发送了高度敏感的信息。

    【讨论】:

      【解决方案3】:

      这个错误对多线程程序有什么影响?

      99.999% 的时间,什么都没有;第二次调用close() 将失败,errno 设置为EBADF,生活将继续。

      另外 0.001% 的时间,另一个线程将在您的线程中两个 close() 调用执行之间的确切瞬间运行并调用 open(),而另一个线程的 open() 调用将返回与您的 fd 局部变量设置为相同的文件描述符值(因为运行时允许在关闭后重新使用文件描述符值)...然后您的线程将再次运行,并且您的第二次调用到close(fd) 将关闭另一个线程的套接字(!)

      此时,使用该文件描述符的其他线程的网络调用将开始出错并显示EBADF(因为它正在尝试使用现已关闭的文件描述符),您将度过几个不愉快的小时/数天/数周的时间试图找出为什么您的程序的网络似乎在一个蓝月亮中随机失败。

      【讨论】:

      • 哦,比这更糟糕。它们可能不会出错,因为另一个线程可能会打开不同的文件或套接字并获得相同的描述符。他们可能成功并将私人信息发送到不受信任的目的地。
      • 1) 坏线程关闭描述符 4。2) 受害者线程打开描述符 4。3) 坏线程再次关闭描述符 4。 4) 另一个受害线程打开描述符 4。 5) 第一个受害线程现在写入连接,第二个受害线程打开认为它正在写入它打开的任何内容。
      猜你喜欢
      • 2020-12-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-31
      • 1970-01-01
      • 1970-01-01
      • 2021-12-20
      相关资源
      最近更新 更多