2010-04-06 16 views
0

作为一个c编码器现在 - 既不是新手也不是专家。现在,我在PPC Linux上有一个C语言的守护进程应用程序。我使用PHP的socket_connect作为客户端来本地连接到此服务。服务器使用epoll通过Unix套接字复用连接。用户提交的字符串是使用strstr()解析某些字符/单词的,如果找到,则会同时产生4个可连接的线程到不同的网站。我使用套接字,连接,写入和读取,在每个线程的端口80上通过TCP与上述网络服务器进行交互。所有连接和写入似乎都很成功。然而,向Web服务器套接字读取失败,但(A)所有3个线程似乎都挂起,只有一个线程返回-1,errno设置为104.响应线程需要10分钟 - 永恒:-(。*我在某处读到104(EINTR?),它在网络环境中暗示......'连接被同级重置';或(B)来自3个线程的0字节,并且4个线程中只有1个实际返回我使用线程安全(和可重入)libc函数,如strtok_r,gethostbyname_r等多线程应用程序中的套接字读取返回零字节或EINTR(104)

*我怀疑所说的网络主机实际上是重置连接,因为当我运行一个单线程独立(其他所有的东西都是相等的)时,所有的东西都可以正常工作,但是当然是串联不是平行的。还有第二个问题(oops),我不能回写到连接到我的epoll-ed Unix套接字的客户端。我的守护程序应用程序将挂起并永久保持CPU> 100%。然而,没有什么是写给客户端的。确保客户端(一个非常典型的PHP套接字应用程序)在发生这种情况时还没有关闭连接 - 也没有检测到任何错误。有任何想法吗?

即使使用Valgrind,GDB或大量日志记录,我也无法弄清楚什么是错误的。请尽可能帮助你。

+2

尝试在'strace'下运行您的程序以获取有关正在发生的更多信息。您也可以尝试wireshark查看通过网络发送和接收的内容。 – mark4o 2010-04-06 05:01:05

+0

errno 104是ECONNRESET(由对等方重置连接),而不是EINTR。 – mark4o 2010-04-06 05:01:41

回答

0

是的,读/写是线程安全的。但是,如果你正在使用它们,请注意gethostbyname()和getservbyname() - 它们会返回指向静态数据的指针,并且可能不是线程安全的。

errno 104是ECONNREFUSED(而不是EINTR)。使用strerror或perror获取特定errno代码的文本错误消息(如'通过对等方重置连接')。

找出错误的最好方法是做非常详细的日志记录 - 记录每个操作的结果,以及连接到的IP地址/端口,读取/写入的字节数,线程ID等详细信息等等。当然,请确保您的日志记录代码是线程安全的:-)

+0

感谢您提出有用的建议。我确认(正如我前面提到的)我使用线程安全和可重入版本gethostbyname_r,strtok_r等。 另外,我已经完成了所有可能的日志记录,以确切地确定在哪里看到代码将会死去 - 在阅读!不幸的是,我不能要求'读'来注销它的内部,我只能等待接收它的输出和错误代码。 – EdNdee 2010-04-06 06:47:34

0

10分钟后获取ECONNRESET听起来像是连接超时的结果。 Web服务器没有发送数据,或者您的应用程序没有收到数据。

要测试前者,请将Wireshark等程序连接到本地环回设备,并查找您正在使用的端口的流量。

对于以后,请看看epoll()手册页。他们提到了使用边缘触发事件可能导致锁定的情况,因为缓冲区中仍有数据,但没有新数据进入,因此不会触发新事件。