php sigpipe,遭遇SIGPIPE[转]

php sigpipe,遭遇SIGPIPE[转]转自:http://www.diybl.com/course/3_program/c++/cppjs/20090831/173152.html我写了一个服务器程序,在Windows下在cygwin环境编译后执行,然后用C#写了多线程客户端进行压力测试.程序一直运行正常.但当在Linux下测试时,总是莫名退出.最后跟踪到是write调用导致退出.用gdb执行程序,退出时提示”Broken…

大家好,又见面了,我是你们的朋友全栈君。

转自:

http://www.diybl.com/course/3_program/c++/cppjs/20090831/173152.html

我写了一个服务器程序,

在Windows下在cygwin环境编译后执行, 然后用C#写了多线程客户端进行压力测试. 程序一直运行正常.

但当在Linux下测试时, 总是莫名退出. 最后跟踪到是write调用导致退出. 用gdb执行程序, 退出时提示”Broken

pipe”.

最后问题确定为, 对一个对端已经关闭的socket调用两次write,

第二次将会生成SIGPIPE信号, 该信号默认结束进程.

具体的分析可以结合TCP的”四次握手”关闭. TCP是全双工的信道,

可以看作两条单工信道, TCP连接两端的两个端点各负责一条. 当对端调用close时, 虽然本意是关闭整个两条信道,

但本端只是收到FIN包. 按照TCP协议的语义, 表示对端只是关闭了其所负责的那一条单工信道, 仍然可以继续接收数据. 也就是说,

因为TCP协议的限制, 一个端点无法获知对端的socket是调用了close还是shutdown.

a4c26d1e5885305701be709a3d33442f.png 截图来自: UNPv1

对一个已经收到FIN包的socket调用read方法,

如果接收缓冲已空, 则返回0, 这就是常说的表示连接关闭. 但第一次对其调用write方法时, 如果发送缓冲没问题,

会返回正确写入(发送). 但发送的报文会导致对端发送RST报文, 因为对端的socket已经调用了close, 完全关闭, 既不发送,

也不接收数据. 所以, 第二次调用write方法(假设在收到RST之后), 会生成SIGPIPE信号, 导致进程退出.

为了避免进程退出, 可以捕获SIGPIPE信号, 或者忽略它,

给它设置SIG_IGN信号处理函数:

signal(SIGPIPE, SIG_IGN);

这样, 第二次调用write方法时, 会返回-1,

同时errno置为SIGPIPE. 程序便能知道对端已经关闭.

PS: Linux下的SIGALRM似乎会每1秒钟往后偏移1毫秒,

但Windows下经过测试完全准时, 不差1毫秒.

忽略SIGPIPE信号的方法

http://hi.baidu.com/greathongjian/blog/item/2f695643091885139213c65a.html

struct sigaction

sa;

sa.sa_handler = SIG_IGN;//设定接受到指定信号后的动作为忽略

sa.sa_flags = 0;if (sigemptyset(&sa.sa_mask)

== -1 || //初始化信号集为空

sigaction(SIGPIPE, &sa, 0) == -1)

{ //屏蔽SIGPIPE信号

perror(“failed to ignore SIGPIPE; sigaction”);

exit(EXIT_FAILURE);

}

pthread线程里如何屏蔽SIGPIPE异常

hi.baidu.com/ailacy/blog/item/a7eb65f8b8b55707d8f9fdd5.html

http://bbs2.chinaunix.net/viewthread.php?tid=985166&extra=&page=1

在pthread中,可能会遇到Program

received signal SIGPIPE, Broken

pipe的问题,解决方法是每一个线程启动之前时,先执行下面代码:

#ifndef WIN32

sigset_t signal_mask;

sigemptyset (&signal_mask);

sigaddset (&signal_mask, SIGPIPE);

int rc = pthread_sigmask (SIG_BLOCK, &signal_mask,

NULL);

if (rc != 0) {

printf(“block sigpipe error\n”);

} #endif 当然,这只是多种方法之一~

根据赖半仙的使用经验,只要在main函数一开始就写入上面这段代码,就能屏蔽掉pthread线程中的SIGPIPE

[linux]

SIGPIPE信号及其处理

http://hi.baidu.com/mckeyzhang/blog/item/d647f26034eee542eaf8f823.html

在linux下写socket的程序的时候,如果尝试send到一个disconnected

socket上,就会让底层抛出一个SIGPIPE信号。

这个信号的缺省处理方法是退出进程,大多数时候这都不是我们期望的。因此我们需要重载这个信号的处理方法。调用以下代码,即可安全的屏蔽SIGPIPE:

struct sigaction sa;

sa.sa_handler = SIG_IGN;

sigaction( SIGPIPE, &sa, 0 );

//======================================================================

SIGPIPE

From Wikipedia, the free

encyclopedia

SIGPIPE

Description

Write on a pipe with no one to read it

Default action

Abnormal termination of the process

SA_SIGINFOmacros

one

On POSIX-compliant

platforms, SIGPIPE is

the signal raised

when a computer

program attempts to write to apipe without

a process connected to the other end.

The symbolic

constant for SIGPIPE is defined in

the header

file signal.h. Symbolic signal names are

used because signal numbers can vary across platforms.

Etymology

SIG is a

common prefix for

signal names. PIPE refers to the

Unix

Description

Unix supports the principle

of piping,

which allows processes to send data to other processes without the

need for creating temporary files. When a pipe is broken, the

process writing to it is sent the SIGPIPE signal. The default

reaction to this signal for a process is to terminate.

A simple example of piping is the

following.

ps l | head

This command, when run on

a Unix-like machine

(including Linux),

returns a list of processes, limited to ten lines.

returns a

list of all processes (including those of other users).

selects the first ten

lines.

When ps has written ten

lines, head has received all

it needs and exits. ps will receive a

SIGPIPE when it tries to write the remaining lines, causing it to

terminate as well: It is no use writing data that no one will use.

It is also possible that the reading process terminates while

reading the data. This will also cause SIGPIPE to be sent to the

writing process.

One can ignore SIGPIPE (using, for

example, the signal system

call). In this case, all system calls that would cause SIGPIPE

to be sent will return -1 and set to

EPIPE.

Uinx 下 Broken pipe 问题

前段时间在处理延时函数时遇到过 “Alarm clock”

信号问题(见我的 “Unix C 延时函数小结”)。现在测试中还遇到了 “Broken pipe”

信号问题,同样产生这个信号程序就中止了。 我的程序产生这个信号的原因是: client端通过 pipe 发送信息到server端后,就关闭client端, 这时server端,返回信息给 client

端时就产生Broken pipe 信号了。 对于产生信号,我们可以在产生信号前利用方法 signal(int signum, sighandler_t handler)

设置信号的处理。如果没有调用此方法,系统就会调用默认处理方法:中止程序,显示提示信息(就是我们经常遇到的问题)。我们可以调用系统的处理方法,也可

以自定义处理方法。 系统里边定义了三种处理方法: 1)SIG_DFL 2)SIG_IGN 3)SIG_ERR 项目中我调用了 signal(SIGALRM, SIG_IGN) 和 signal(SIGPIPE, SIG_IGN), 这样产生

SIGALAM 和 SIGPIPE

信号时就不会中止程序,直接把这个信号忽略掉。 自定义处理方法:

C代码

voidsignal_handle(ing signo)

{

//do something;

}

intmain()

{

signal(SIGPIPE, signal_handle);

……

}

声明:JavaEye文章版权属于作者,受法律保护。没有作者书面许可不得转载。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/139109.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • encode-decode结构

    encode-decode结构encode的输入是变长的序列向量,每个向量之间会在batch内填充为固定长度,神经网络限制,不能输入变长的向量。encode输出固定长度的向量,但序列数量和输入数量保持不变,也就是一个输入产生一个输出。每个输出之间是独立的。encode的网络可以不固定,比如常见nlp任务用rnn,。encode将可变序列编码为固定状态,decode将固定状态输入映射为其它可变序列。decode的网络可以不固定,其中ctc结合search策略也可以用来做decode。通用的“编码器-解码器”接口定义:fro.

    2022年10月7日
    3
  • fiddler4手机抓包教程(安卓抓包教程)

    fiddler手机抓包原理及详细的相关配置

    2022年4月11日
    349
  • linux操作系统常用操作命令_运行cmd命令大全

    linux操作系统常用操作命令_运行cmd命令大全一.文件操作命令1.df 显示磁盘使用情况2.du 显示文件系统使用情况3.ls 显示目录普通使用:ls  ls-l  ll查看多个目录:ls/ /ect 查看/和/etc下的文件查看隐藏文件:ls-a 4.cd 切换工作目录切换到根目录:cd/切换到上一级目录:cd..切换到当前用户家目录:cd切换到普…

    2022年9月1日
    8
  • Oracle列转行函数LISTAGG() WITHIN GROUP ()的使用方法

    Oracle列转行函数LISTAGG() WITHIN GROUP ()的使用方法前言:最近在写一些比较复杂的SQL,是一些统计分析类的,动不动就三四百行,也是首次写那么长的SQL,有用到一些奇形怪状的SQL函数,在这里结合网上的例子做一些笔记,以后用到不记得用法可以翻出来看!1.基础用法:LISTAGG(XXX,XXX)WITHINGROUP(ORDERBYXXX),就像聚合函数一样,通过Groupby语句,把每个Group的一个字段,拼接起来…

    2025年8月3日
    2
  • 【2021最新版】MyBatis面试题总结(38道题含答案解析)[通俗易懂]

    【2021最新版】MyBatis面试题总结(38道题含答案解析)[通俗易懂]文章目录1、什么是Mybatis?2、Mybaits的优点?3、MyBatis框架的缺点?4、MyBatis框架适用场合5、MyBatis与Hibernate有哪些不同?6、#{}和${}的区别是什么?7、当实体类中的属性名和表中的字段名不一样,怎么办?8、模糊查询like语句该怎么写?9、通常一个Xml映射文件,都会写一个Dao接口与之对应,请问,这个Dao接口的工作原理是什么?Dao接口里的方法,参数不同时,方法能重载吗?10、Mybatis是如何进行分页的?分页插件的原理是什么?11、Myba

    2022年5月1日
    47
  • 进程和线程的区别(超详细)

    进程和线程的区别(超详细)进程和线程进程一个在内存中运行的应用程序。每个进程都有自己独立的一块内存空间,一个进程可以有多个线程,比如在Windows系统中,一个运行的xx.exe就是一个进程。线程进程中的一个执行任务(控制单元),负责当前进程中程序的执行。一个进程至少有一个线程,一个进程可以运行多个线程,多个线程可共享数据。与进程不同的是同类的多个线程共享进程的堆和方法区资源,但每个线程有自己的程序计数器、虚拟…

    2022年7月25日
    13

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号