[PATCH] python: Workaround UNIX socket path length limits

James Page james.page at ubuntu.com
Wed Jan 16 10:52:59 UTC 2013


UNIX socket paths have a limit in terms of length.  On Linux
this is 103 characters.

This is a problem in Debian/Ubuntu buildds which can generate
quite long paths.

This patch works around this issue by detecting when socket
connection/binding fails due to this issue and accessing the
socket path using a file descriptor path in /proc/self/fd.

The workaround is limited to Linux.

This is based on similar code in the C parts of OpenvSwitch.

Signed-off-by: James Page <james.page at ubuntu.com>
---
 python/ovs/socket_util.py | 39 +++++++++++++++++++++++++++++++++++++--
 1 file changed, 37 insertions(+), 2 deletions(-)

diff --git a/python/ovs/socket_util.py b/python/ovs/socket_util.py
index 8fecbc7..7bfefc4 100644
--- a/python/ovs/socket_util.py
+++ b/python/ovs/socket_util.py
@@ -70,9 +70,44 @@ 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):
-- 
1.8.0



More information about the dev mailing list