From 012c93ae400a813742355959ef46369befadf258 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 16 Jun 2011 12:26:24 +0200 Subject: [PATCH] [IMP] OSX handling of socket shutdown in TinySocketClientThread When the client closes its socket, on OSX it closes the server one as well, leading to an errno.ENOTCONN when trying to shut it down. Also use the unified socket-closing function to handle tinysocket bzr revid: xmo@openerp.com-20110616102624-vixxow6twsx7j84s --- openerp/netsvc.py | 40 +++++++++++++++++++------------- openerp/service/netrpc_server.py | 13 +---------- openerp/tiny_socket.py | 5 ++-- 3 files changed, 28 insertions(+), 30 deletions(-) diff --git a/openerp/netsvc.py b/openerp/netsvc.py index 4d01d5295fe..e1d333fd78b 100644 --- a/openerp/netsvc.py +++ b/openerp/netsvc.py @@ -26,22 +26,42 @@ import cgitb import errno +import heapq import logging import logging.handlers import os +import platform +import release import socket import sys import threading import time -import release -from pprint import pformat import warnings -import heapq +from pprint import pformat # TODO modules that import netsvc only for things from loglevels must be changed to use loglevels. from loglevels import * import tools +def close_socket(sock): + """ Closes a socket instance cleanly + + :param sock: the network socket to close + :type sock: socket.socket + """ + try: + sock.shutdown(socket.SHUT_RDWR) + except socket.error, e: + ## On OSX, socket shutdowns both sides if any side closes it + ## causing an error 57 'Socket is not connected' on shutdown + ## of the other side (or something), see + ## http://bugs.python.org/issue4397 + ## note: stdlib fixed test, not behavior + if e.errno != errno.ENOTCONN or platform.system() != 'Darwin': + raise + sock.close() + + class Service(object): """ Base class for *Local* services @@ -381,19 +401,7 @@ class Server: return '\n'.join(res) def _close_socket(self): - if os.name != 'nt': - try: - self.socket.shutdown(getattr(socket, 'SHUT_RDWR', 2)) - except socket.error, e: - if e.errno != errno.ENOTCONN: raise - # OSX, socket shutdowns both sides if any side closes it - # causing an error 57 'Socket is not connected' on shutdown - # of the other side (or something), see - # http://bugs.python.org/issue4397 - self.__logger.debug( - '"%s" when shutting down server socket, ' - 'this is normal under OS X', e) - self.socket.close() + close_socket(self.socket) class OpenERPDispatcherException(Exception): def __init__(self, exception, traceback): diff --git a/openerp/service/netrpc_server.py b/openerp/service/netrpc_server.py index ac3cd724a45..b4d5a74dc48 100644 --- a/openerp/service/netrpc_server.py +++ b/openerp/service/netrpc_server.py @@ -45,16 +45,6 @@ class TinySocketClientThread(threading.Thread, netsvc.OpenERPDispatcher): self.sock.settimeout(1200) self.threads = threads - def __del__(self): - if self.sock: - try: - self.socket.shutdown( - getattr(socket, 'SHUT_RDWR', 2)) - except Exception: - pass - # That should garbage-collect and close it, too - self.sock = None - def run(self): self.running = True try: @@ -93,8 +83,7 @@ class TinySocketClientThread(threading.Thread, netsvc.OpenERPDispatcher): logging.getLogger('web-services').exception("netrpc: cannot deliver exception message to client") break - self.sock.shutdown(socket.SHUT_RDWR) - self.sock.close() + netsvc.close_socket(self.sock) self.sock = None self.threads.remove(self) self.running = False diff --git a/openerp/tiny_socket.py b/openerp/tiny_socket.py index 44f7db04f01..cc0f09ec976 100644 --- a/openerp/tiny_socket.py +++ b/openerp/tiny_socket.py @@ -24,6 +24,8 @@ import cPickle import cStringIO import marshal +import netsvc + class Myexception(Exception): """ custome exception object store @@ -56,8 +58,7 @@ class mysocket: self.sock.connect((host, int(port))) def disconnect(self): - self.sock.shutdown(socket.SHUT_RDWR) - self.sock.close() + netsvc.close_socket(self.sock) def mysend(self, msg, exception=False, traceback=None): msg = cPickle.dumps([msg,traceback])