X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=python%2Fovs%2Fsocket_util.py;h=7bfefc49cdf1ac1aa25ff2a387cb5d0a8b444199;hb=ea7655d9f9d38a3af7250de8ba0b89115b5f4a5e;hp=845511e3b209a556ca353b27b43fb308e730ba6d;hpb=67656b9ff297f305b3bfcca2868e8e870e108283;p=sliver-openvswitch.git diff --git a/python/ovs/socket_util.py b/python/ovs/socket_util.py index 845511e3b..7bfefc49c 100644 --- a/python/ovs/socket_util.py +++ b/python/ovs/socket_util.py @@ -70,16 +70,65 @@ def make_unix_socket(style, nonblock, bind_path, connect_path): return 0, sock except socket.error, e: sock.close() - if bind_path is not None: + if (bind_path is not None and + os.path.exists(bind_path)): ovs.fatal_signal.unlink_file_now(bind_path) - return get_exception_errno(e), None + eno = ovs.socket_util.get_exception_errno(e) + if (eno == "AF_UNIX path too long" and + os.uname()[0] == "Linux"): + short_connect_path = None + short_bind_path = None + connect_dirfd = None + bind_dirfd = None + # Try workaround using /proc/self/fd + if connect_path is not None: + dirname = os.path.dirname(connect_path) + basename = os.path.basename(connect_path) + try: + connect_dirfd = os.open(dirname, os.O_DIRECTORY | os.O_RDONLY) + except OSError, err: + return get_exception_errno(e), None + short_connect_path = "/proc/self/fd/%d/%s" % (connect_dirfd, basename) + + if bind_path is not None: + dirname = os.path.dirname(bind_path) + basename = os.path.basename(bind_path) + try: + bind_dirfd = os.open(dirname, os.O_DIRECTORY | os.O_RDONLY) + except OSError, err: + return get_exception_errno(e), None + short_bind_path = "/proc/self/fd/%d/%s" % (bind_dirfd, basename) + + try: + return make_unix_socket(style, nonblock, short_bind_path, short_connect_path) + finally: + if connect_dirfd is not None: + os.close(connect_dirfd) + if bind_dirfd is not None: + os.close(bind_dirfd) + else: + return get_exception_errno(e), None def check_connection_completion(sock): p = ovs.poller.SelectPoll() - p.register(sock, select.POLLOUT) - if len(p.poll(0)) == 1: - return get_socket_error(sock) + p.register(sock, ovs.poller.POLLOUT) + pfds = p.poll(0) + if len(pfds) == 1: + revents = pfds[0][1] + if revents & ovs.poller.POLLERR: + try: + # The following should raise an exception. + socket.send("\0", socket.MSG_DONTWAIT) + + # (Here's where we end up if it didn't.) + # XXX rate-limit + vlog.err("poll return POLLERR but send succeeded") + return errno.EPROTO + except socket.error, e: + return get_exception_errno(e) + else: + return 0 else: return errno.EAGAIN @@ -88,13 +137,13 @@ def inet_parse_active(target, default_port): address = target.split(":") host_name = address[0] if not host_name: - raise Exception("%s: bad peer name format" % target) + raise ValueError("%s: bad peer name format" % target) if len(address) >= 2: port = int(address[1]) elif default_port: port = default_port else: - raise Exception("%s: port number must be specified" % target) + raise ValueError("%s: port number must be specified" % target) return (host_name, port) @@ -119,12 +168,6 @@ def inet_open_active(style, target, default_port, dscp): return get_exception_errno(e), None -def get_socket_error(sock): - """Returns the errno value associated with 'socket' (0 if no error) and - resets the socket's error status.""" - return sock.getsockopt(socket.SOL_SOCKET, socket.SO_ERROR) - - def get_exception_errno(e): """A lot of methods on Python socket objects raise socket.error, but that exception is documented as having two completely different forms of @@ -182,11 +225,11 @@ def set_nonblocking(sock): sock.setblocking(0) except socket.error, e: vlog.err("could not set nonblocking mode on socket: %s" - % os.strerror(get_socket_error(e))) + % os.strerror(get_exception_errno(e))) def set_dscp(sock, dscp): if dscp > 63: - raise Exception("Invalid dscp %d" % dscp) + raise ValueError("Invalid dscp %d" % dscp) val = dscp << 2 sock.setsockopt(socket.IPPROTO_IP, socket.IP_TOS, val)