c - 在 Linux 上处理多线程损坏管道案例的服务器端套接字最佳实践是什么?
问题描述
考虑到在 Linux 上是 C 语言的新手,我已经完成了套接字编程场景,在这些场景中你必须处理 SIGPIPE 问题并且我遇到了以下情况:
1- 捕获进程的 sigaction 然后继续,这等于忽略信号。
struct sigaction sginal_action;
memset(&sginal_action, 0, sizeof (sginal_action));
sginal_action.sa_handler = SIG_IGN;
sginal_action.sa_flags = SA_RESTART;
if (sigaction(SIGPIPE, &sginal_action, null)) {
perror("signal action error");
}
2-忽略线程使用的信号
sigset_t sigpipe_mask;
sigemptyset(&sigpipe_mask);
sigaddset(&sigpipe_mask, SIGPIPE);
sigset_t saved_mask;
if (pthread_sigmask(SA_RESTART, &sigpipe_mask, &saved_mask) == -1) {
perror("pthread_sigmask");
}
- 现在一切正常,但我需要关于此测试用例行为的答案:
1- 服务器接受来自用户 A 的套接字,文件描述符为 int 7
2- 我运行冗长的 SQL 语句,需要 25 秒
3- 在 20 秒时客户端关闭套接字
4- 在 21 秒 Linux 内核发送了 SIGPIPE
5- 在 22 秒进程忽略了 SIGPIPE 并继续使用文件描述符 7,因为没有任何信号出现任何问题
6- 在 23 秒服务器接受来自用户 B 的套接字,文件描述符为 int 7 , 再次!
7- 用户 B 授权需要 2 秒,在用户 A 的 25 秒完成。
8-核心问题开始在第二个 25 写入(file_dsciptor,缓冲区,缓冲区大小);来自两个线程的数据都将写入用户 A 和用户 B 通道
9- 碰巧用户 B 无权登录服务器,但在服务器关闭线程 B 的文件描述符 7 之前,客户端 A 的线程 A 写入文件描述符 7 和由于套接字文件描述符 7 的重用,客户端 B 收到了重要数据!
我的问题
是,这种情况是错误的并且永远不会发生吗?
还是有可能发生,但有正确的方法可以应用?
并且是否有一个 C 系统调用函数来停止通过套接字连接重用 file_discriptor?
或者应该做些什么来确保打开的频道不会与另一个频道冲突,比如我猜的唯一文件描述符?
解决方案
(正常)SIGPIPE
本质上是一个同步信号。您会得到它以响应您所做的事情,即尝试写入被另一方关闭的管道/套接字/FIFO。忽略SIGPIPE
是无害的,因为如果您这样做,您仍然会以通常报告同步错误的方式获知错误:通过失败的返回码并errno
设置为适当的错误号 ( EPIPE
)。在这种情况下,我认为SIGPIPE
在继续检查错误的同时忽略将是最好的方法,无论您使用的是什么 POSIX 平台。
关于您的示例,您在第 5 点的假设是“没有任何信号出错”是不正确的。会有信号。它不会是一个信号,而是一个呼叫EPIPE
失败。write
推荐阅读
- facebook - 如何在 Facebook 上发布自己的视频,使其不会自动播放?
- ios - SwiftUI 文本不会扩展到多行
- android - 使用 Kotlin DSL 发布库
- javascript - 使用 Weather API 并按日期排序
- xml - XSLT:复制 XML 的节点并更改命名空间
- oracle - 通过过程执行没有得到正确的输出
- mysql - Mysql加入同一张表而不反向
- ffmpeg - h264_mp4toannexb 过滤器在 ffmpeg 连接时无法接收输出数据包
- python - Regex expression to merge elements together
- django - Is there a way to determinate the type of request received in a Class Based View with Django Rest Framework?