调用writev收到信号SIGPIPE问题分析记录

问题描述

在调试服务程序,发现调用writev()函数之后,程序接收到SIGPIPE导致程序异常终止。

writev received signal SIGPIPE, Broken pipe.

问题分析

1.查询writev返回SIGPIPE信号的原因

通过查询资料,这种报错是主要是因为向一个已经关闭的套接字(socket)写入数据时,由此可知可能是套接字出现了问题,我的代码逻辑是connect()成功之后直接调用writev(),按道理不应该是一个关闭的套接字。

2.分析套接字是否已经关闭

我首先观察fd等数据,发现fd数值比较正常,那么我怎么才能确认自己的套接字是正常的呢?我的办法是抓包,如果这个套接字是正常的,那么肯定会存在三次握手的报文。通过抓包,发现我调用connect()函数之后并没有出现相应的报文信息。

3.确认是connect()函数出现异常

gdb调试connect的入参,没有发现任何异常,甚至于我打印 struct sockaddr对象内部也完全没有问题。

我决定采取比较法分析问题,我自己实现了一个demo程序,发现connect()是成功的。

然后我在服务内部采取注释法,刨除掉所有不相关的代码,只实现connect功能,发现网络请求是正常的。

通过不断排除法,最终发现问题出现在connect()入参struct sockaddr上。

仔细分析代码,发现struct sockaddr对象是一个无效的对象,因此这个对象是一个栈变量,并且这个栈变量已经失效了,但是我仍然使用他作为connect的参数导致了异常。

问题小结

1.connect()函数返回成功并不表示三次握手已经成功,需要通过抓包类似的手段来进行确认;

2.已经失效的变量可能内部数据还没有改变,但是这个变量已经是野指针了,编程中需要注意这一点。

 

posted on 2025-03-20 09:12  寒魔影  阅读(21)  评论(0)    收藏  举报

导航