[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
This commit is contained in:
parent
abb606aa7c
commit
012c93ae40
|
@ -26,22 +26,42 @@
|
||||||
|
|
||||||
import cgitb
|
import cgitb
|
||||||
import errno
|
import errno
|
||||||
|
import heapq
|
||||||
import logging
|
import logging
|
||||||
import logging.handlers
|
import logging.handlers
|
||||||
import os
|
import os
|
||||||
|
import platform
|
||||||
|
import release
|
||||||
import socket
|
import socket
|
||||||
import sys
|
import sys
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
import release
|
|
||||||
from pprint import pformat
|
|
||||||
import warnings
|
import warnings
|
||||||
import heapq
|
from pprint import pformat
|
||||||
|
|
||||||
# TODO modules that import netsvc only for things from loglevels must be changed to use loglevels.
|
# TODO modules that import netsvc only for things from loglevels must be changed to use loglevels.
|
||||||
from loglevels import *
|
from loglevels import *
|
||||||
import tools
|
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):
|
class Service(object):
|
||||||
""" Base class for *Local* services
|
""" Base class for *Local* services
|
||||||
|
|
||||||
|
@ -381,19 +401,7 @@ class Server:
|
||||||
return '\n'.join(res)
|
return '\n'.join(res)
|
||||||
|
|
||||||
def _close_socket(self):
|
def _close_socket(self):
|
||||||
if os.name != 'nt':
|
close_socket(self.socket)
|
||||||
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()
|
|
||||||
|
|
||||||
class OpenERPDispatcherException(Exception):
|
class OpenERPDispatcherException(Exception):
|
||||||
def __init__(self, exception, traceback):
|
def __init__(self, exception, traceback):
|
||||||
|
|
|
@ -45,16 +45,6 @@ class TinySocketClientThread(threading.Thread, netsvc.OpenERPDispatcher):
|
||||||
self.sock.settimeout(1200)
|
self.sock.settimeout(1200)
|
||||||
self.threads = threads
|
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):
|
def run(self):
|
||||||
self.running = True
|
self.running = True
|
||||||
try:
|
try:
|
||||||
|
@ -93,8 +83,7 @@ class TinySocketClientThread(threading.Thread, netsvc.OpenERPDispatcher):
|
||||||
logging.getLogger('web-services').exception("netrpc: cannot deliver exception message to client")
|
logging.getLogger('web-services').exception("netrpc: cannot deliver exception message to client")
|
||||||
break
|
break
|
||||||
|
|
||||||
self.sock.shutdown(socket.SHUT_RDWR)
|
netsvc.close_socket(self.sock)
|
||||||
self.sock.close()
|
|
||||||
self.sock = None
|
self.sock = None
|
||||||
self.threads.remove(self)
|
self.threads.remove(self)
|
||||||
self.running = False
|
self.running = False
|
||||||
|
|
|
@ -24,6 +24,8 @@ import cPickle
|
||||||
import cStringIO
|
import cStringIO
|
||||||
import marshal
|
import marshal
|
||||||
|
|
||||||
|
import netsvc
|
||||||
|
|
||||||
class Myexception(Exception):
|
class Myexception(Exception):
|
||||||
"""
|
"""
|
||||||
custome exception object store
|
custome exception object store
|
||||||
|
@ -56,8 +58,7 @@ class mysocket:
|
||||||
self.sock.connect((host, int(port)))
|
self.sock.connect((host, int(port)))
|
||||||
|
|
||||||
def disconnect(self):
|
def disconnect(self):
|
||||||
self.sock.shutdown(socket.SHUT_RDWR)
|
netsvc.close_socket(self.sock)
|
||||||
self.sock.close()
|
|
||||||
|
|
||||||
def mysend(self, msg, exception=False, traceback=None):
|
def mysend(self, msg, exception=False, traceback=None):
|
||||||
msg = cPickle.dumps([msg,traceback])
|
msg = cPickle.dumps([msg,traceback])
|
||||||
|
|
Loading…
Reference in New Issue