Python提示[Errno32]Brokenpipe导致线程crash错误解决方法
本文实例讲述了Python提示[Errno32]Brokenpipe导致线程crash错误解决方法。分享给大家供大家参考。具体方法如下:
1.错误现象
ThreadingHTTPServer实现的http服务,如果客户端在服务器返回前,主动断开连接,则服务器端会报[Errno32]Brokenpipe错,并导致处理线程crash.
下面先看个例子,python版本:2.7
示例代码
#!coding=utf-8
importos
importtime
importsocket
importthreading
fromBaseHTTPServerimportHTTPServer,BaseHTTPRequestHandler
fromSocketServerimportThreadingMixIn
classRequestHandler(BaseHTTPRequestHandler):
defdo_GET(self):
"""
处理get请求
"""
query=self.path
print"query:%sthread=%s"%(query,str(threading.current_thread()))
#ret_str="<html>"+self.path+"<br>"+str(self.server)+"<br>"+str(self.responses)+ "</html>"
ret_str="<html>"+self.path+"<br>"+str(self.server)+ "</html>"
time.sleep(5)
try:
self.send_response(200)
self.send_header("Content-type","text/html")
self.end_headers()
self.wfile.write(ret_str)
exceptsocket.error,e:
print"socket.error:Connectionbroke.Aborting"+str(e)
self.wfile._sock.close() #closesocket
self.wfile._sock=None
returnFalse
print"successprodquery:%s"%(query)
returnTrue
#多线程处理
classThreadingHTTPServer(ThreadingMixIn,HTTPServer):
pass
if__name__=="__main__":
serveraddr=("",9001)
ser=ThreadingHTTPServer(serveraddr,RequestHandler)
ser.serve_forever()
sys.exit(0)
运行服务
./thread_http_server_error.py
第1次curl,等待返回
<html>/hello1<br><__main__.ThreadingHTTPServerinstanceat0x37483b0></html>[~]$
此时服务器端输出日志如下:
$./thread_http_server_error.py
query:/hello1thread=
search041142.sqa.cm4.tbsite.net?-[15/May/201415:02:27]“GET/hello1HTTP/1.1″200-
successprodquery:/hello1
第2次curl,不等待返回,ctrl+C来模拟客户端断开
[~]$ctrl+C
此时服务器端输出日志如下:
search041142.sqa.cm4.tbsite.net?-[15/May/201415:33:10]“GET/hello2HTTP/1.1″200-
socket.error:Connectionbroke.Aborting[Errno32]Brokenpipe
—————————————-
Exceptionhappenedduringprocessingofrequestfrom("10.232.41.142′,48769)
Traceback(mostrecentcalllast):
File“/home/wuzhu/tools/python_2_7_1/lib/python2.7/SocketServer.py”,line582,inprocess_request_thread
self.finish_request(request,client_address)
File“/home/wuzhu/tools/python_2_7_1/lib/python2.7/SocketServer.py”,line323,infinish_request
self.RequestHandlerClass(request,client_address,self)
File“/home/wuzhu/tools/python_2_7_1/lib/python2.7/SocketServer.py”,line639,in__init__
self.handle()
File“/home/wuzhu/tools/python_2_7_1/lib/python2.7/BaseHTTPServer.py”,line337,inhandle
self.handle_one_request()
File“/home/wuzhu/tools/python_2_7_1/lib/python2.7/BaseHTTPServer.py”,line326,inhandle_one_request
self.wfile.flush()#actuallysendtheresponseifnotalreadydone.
File“/home/wuzhu/tools/python_2_7_1/lib/python2.7/socket.py”,line303,inflush
self._sock.sendall(view[write_offset:write_offset+buffer_size])
AttributeError:"NoneType"objecthasnoattribute"sendall"
2.原因分析
“[Errno32]Brokenpipe“产生的原因还是比较明确的,由于client在服务器返回前主动断开连接,所以服务器在返回时写socket收到SIGPIPE报错。虽然在我们的程序中也对异常进行了处理,将handler的wfile._sock对象close掉,但python的库里BaseHTTPServer.py中BaseHTTPRequestHandler类的成员函数handle_one_request还是会直接调用wfile.flush,而没有判断wfile是否已经close。
"""HandleasingleHTTPrequest.
Younormallydon"tneedtooverridethismethod;seetheclass
__doc__stringforinformationonhowtohandlespecificHTTP
commandssuchasGETandPOST.
"""
try:
self.raw_requestline=self.rfile.readline(65537)
iflen(self.raw_requestline)>65536:
self.requestline=""
self.request_version=""
self.command=""
self.send_error(414)
return
ifnotself.raw_requestline:
self.close_connection=1
return
ifnotself.parse_request():
#Anerrorcodehasbeensent,justexit
return
mname="do_"+self.command
ifnothasattr(self,mname):
self.send_error(501,"Unsupportedmethod(%r)"%self.command)
return
method=getattr(self,mname)
method()
#没有判断wfile是否已经close就直接调用flush()
self.wfile.flush()#actuallysendtheresponseifnotalreadydone.
exceptsocket.timeout,e:
#areadorawritetimedout. Discardthisconnection
self.log_error("Requesttimedout:%r",e)
self.close_connection=1
return
3.解决办法
只要在RequestHandler重载其基类BaseHTTPRequestHandler的成员函数handle_one_reques(),在调用wfile.flush()前加上wfile是否已经close即可。
#!coding=utf-8
importos
importtime
importsocket
importthreading
fromBaseHTTPServerimportHTTPServer,BaseHTTPRequestHandler
fromSocketServerimportThreadingMixIn
classRequestHandler(BaseHTTPRequestHandler):
defhandle_one_request(self):
"""HandleasingleHTTPrequest.
Younormallydon"tneedtooverridethismethod;seetheclass
__doc__stringforinformationonhowtohandlespecificHTTP
commandssuchasGETandPOST.
"""
try:
self.raw_requestline=self.rfile.readline(65537)
iflen(self.raw_requestline)>65536:
self.requestline=""
self.request_version=""
self.command=""
self.send_error(414)
return
ifnotself.raw_requestline:
self.close_connection=1
return
ifnotself.parse_request():
#Anerrorcodehasbeensent,justexit
return
mname="do_"+self.command
ifnothasattr(self,mname):
self.send_error(501,"Unsupportedmethod(%r)"%self.command)
return
method=getattr(self,mname)
print"beforecalldo_Get"
method()
#增加debuginfo及wfile判断是否已经close
print"aftercalldo_Get"
ifnotself.wfile.closed:
self.wfile.flush()#actuallysendtheresponseifnotalreadydone.
print"afterwfile.flush()"
exceptsocket.timeout,e:
#areadorawritetimedout. Discardthisconnection
self.log_error("Requesttimedout:%r",e)
self.close_connection=1
return
defdo_GET(self):
"""
处理get请求
"""
query=self.path
print"query:%sthread=%s"%(query,str(threading.current_thread()))
ret_str="<html>"+self.path+"<br>"+str(self.server)+ "</html>"
time.sleep(5)
try:
self.send_response(200)
self.send_header("Content-type","text/html")
self.end_headers()
self.wfile.write(ret_str)
exceptsocket.error,e:
print"socket.error:Connectionbroke.Aborting"+str(e)
self.wfile._sock.close()
self.wfile._sock=None
returnFalse
print"successprodquery:%s"%(query)
returnTrue
#多线程处理
classThreadingHTTPServer(ThreadingMixIn,HTTPServer):
pass
if__name__=="__main__":
serveraddr=("",9001)
ser=ThreadingHTTPServer(serveraddr,RequestHandler)
ser.serve_forever()
sys.exit(0)
运行服务
./thread_http_server.py
curl,不等待返回,ctrl+C来模拟客户端断开
[~]$ctrl+C
此时服务器端输出日志如下:
query:/hello2thread=<Thread(Thread-1,started1103210816)>
search041142.sqa.cm4.tbsite.net--[15/May/201415:54:09]"GET/hello2HTTP/1.1"200-
socket.error:Connectionbroke.Aborting[Errno32]Brokenpipe
aftercalldo_Get
afterwfile.flush()
希望本文所述对大家的Python程序设计有所帮助。
相关文章
- python求逆矩阵的方法,Python 如何求矩阵的逆「建议收藏」
- Python进阶37-smtp及Django发邮件
- python中矩阵的转置怎么写_Python 矩阵转置的几种方法小结
- 浙江新增python编程_9月起,浙江省八年级新增Python编程课,未来编程是处理大数据的手段…「建议收藏」
- Python实战-暴力破解zip文件解压密码
- python实现卷积操作
- python中矩阵的转置_[转]Python中的矩阵转置[通俗易懂]
- python判断linux中文件是否存在_Python判断文件是否存在的三种方法
- python读取pkl_Python 读取文件
- Python 生成、识别社会统一信用代码
- python图像识别与提取_图像分类python
- Python win32api_python api文档
- Python Tkinter Gui 常用组件介绍 基本使用
- 【测试开发】python系列教程:Python 运算符
- 用python写一个漂亮的烟花
- Python 打印彩色日志
- python-异常处理和错误调试-异步IO程序的调试方法(二)
- python-Python与PostgreSQL数据库-使用Python执行PostgreSQL查询(一)
- 使用Python执行Linux命令的方法(python调用linux命令)
- 搞定!Linux下快速设置Python环境变量(linux设置python环境变量)
- Python结合MySQL实现信息交互(python与mysql交互)
- Linux查看Python安装路径的方法(linux查看python安装路径)
- 使用 Python 学习面向对象的编程
- python小技巧之批量抓取美女图片
- Python实现全局变量的两个解决方法