xpra icon
Bug tracker and wiki

Ticket #1150: named-pipes-mess.patch

File named-pipes-mess.patch, 6.9 KB (added by Antoine Martin, 4 years ago)

experimenting with tweaks to make named pipes work properly - hard

  • xpra/net/bytestreams.py

     
    5252    import winerror     #@UnresolvedImport
    5353    #on win32, we have to deal with a few more odd error codes:
    5454    #(it would be nicer if those were wrapped using errno instead..)
     55    #maybe we should just inject those from xpra/platform/win32 ?
    5556    WSAEWOULDBLOCK = 10035
    5657    CONTINUE[WSAEWOULDBLOCK] = "WSAEWOULDBLOCK"
    5758
     
    7576        WSAETIMEDOUT        : "WSAETIMEDOUT",
    7677        WSAEHOSTUNREACH     : "WSAEHOSTUNREACH",
    7778        WSAEDISCON          : "WSAEDISCON",
    78         winerror.ERROR_BROKEN_PIPE : "BROKENPIPE",
     79        winerror.ERROR_NO_DATA              : "NO_DATA",
     80        winerror.ERROR_BROKEN_PIPE          : "BROKENPIPE",
     81        winerror.ERROR_PIPE_NOT_CONNECTED   : "PIPE_NOT_CONNECTED",
    7982        })
    8083    #on win32, we want to wait just a little while,
    8184    #to prevent servers spinning wildly on non-blocking sockets:
  • xpra/platform/win32/namedpipes/connection.py

     
    66
    77#@PydevCodeAnalysisIgnore
    88
     9import os
    910import binascii
    10 import win32api     #@UnresolvedImport
     11from xpra.net import ConnectionClosedException
    1112from xpra.net.bytestreams import Connection
     13import win32api                                                             #@UnresolvedImport
    1214from win32pipe import DisconnectNamedPipe                                   #@UnresolvedImport
    1315from win32file import ReadFile, WriteFile, CloseHandle, FlushFileBuffers    #@UnresolvedImport
    1416from pywintypes import error                                                #@UnresolvedImport
     
    1719from xpra.log import Logger
    1820log = Logger("network", "win32")
    1921
     22PIPE_DEBUG = os.environ.get("XPRA_WIN32_PIPE_DEBUG", "0")=="1"
     23PIPE_PATH = "\\\\.\\pipe\\"
    2024
     25IO_ERRORS = {
     26             winerror.ERROR_NO_DATA              : "NO_DATA",
     27             winerror.ERROR_BROKEN_PIPE          : "BROKENPIPE",
     28             winerror.ERROR_PIPE_NOT_CONNECTED   : "PIPE_NOT_CONNECTED",
     29             }
     30
     31
    2132class NamedPipeConnection(Connection):
    2233    def __init__(self, name, pipe_handle):
    2334        Connection.__init__(self, name, "named-pipe")
    2435        self.pipe_handle = pipe_handle
     36        self.target = name
     37        if name.startswith(PIPE_PATH):
     38            self.target = name[len(PIPE_PATH):]
    2539
    2640    def untilConcludes(self, *args):
    2741        try:
    2842            return Connection.untilConcludes(self, *args)
    2943        except error as e:
    30             code = e[0]
    31             raise IOError("%s: %s" % (code, win32api.FormatMessage(code)))
     44            #convert IOErrors into ConnectionClosedException
     45            if e[0] in IO_ERRORS:
     46                self.close()
     47                raise ConnectionClosedException(e[2])
     48            log("windows error: %s", e)
     49            raise
    3250
    3351    def read(self, n):
    3452        return self._read(self._pipe_read, n)
    3553
    36     def _pipe_read(self, buf):
    37         data = []
    38         hr = winerror.ERROR_MORE_DATA
    39         while hr==winerror.ERROR_MORE_DATA:
    40             hr, d = ReadFile(self.pipe_handle, 65536)
    41             data.append(d)
    42         s = b"".join(data)
    43         log("pipe_read: %i / %s", hr, binascii.hexlify(s))
    44         return s
     54    def _pipe_read(self, n):
     55        d = None
     56        while not d:
     57            err, d = ReadFile(self.pipe_handle, n)
     58            if err!=0:
     59                raise ConnectionClosedException(win32api.FormatMessage(err))
     60            if PIPE_DEBUG:
     61                log("pipe_read: %i bytes: %s", len(d), binascii.hexlify(d[:32]))
     62        return d
    4563
    4664    def write(self, buf):
    4765        return self._write(self._pipe_write, buf)
    4866
    4967    def _pipe_write(self, buf):
    50         log("pipe_write: %s", binascii.hexlify(buf))
    51         WriteFile(self.pipe_handle, buf)
     68        if PIPE_DEBUG:
     69            log("pipe_write: %s", binascii.hexlify(buf))
     70        if not WriteFile(self.pipe_handle, buf):
     71            err = win32api.GetLastError()
     72            raise ConnectionClosedException(win32api.FormatMessage(err))
    5273        FlushFileBuffers(self.pipe_handle)
    53         #SetFilePointer(self.pipe_handle, 0, FILE_BEGIN)
    5474        return len(buf)
    5575
    5676    def close(self):
     77        log("close() named pipe %s", self.target)
     78        self.set_active(False)
     79        ph = self.pipe_handle
     80        if ph is None:
     81            return
     82        self.pipe_handle = None
    5783        try:
    58             DisconnectNamedPipe(self.pipe_handle)
     84            DisconnectNamedPipe(ph)
    5985        except Exception as e:
    60             log.error("Error: DisconnectNamedPipe(%s) %s", self.pipe_handle, e)
     86            log("DisconnectNamedPipe(%s) %s", ph, e)
    6187        try:
    62             CloseHandle(self.pipe_handle)
     88            CloseHandle(ph)
    6389        except Exception as e:
    64             log.error("Error: CloseHandle(%s) %s", self.pipe_handle, e)
     90            log("CloseHandle(%s) %s", ph, e)
    6591
    6692    def __repr__(self):
    6793        return "%s named-pipe" % self.target
  • xpra/platform/win32/namedpipes/listener.py

     
    1414
    1515import pywintypes, winerror            #@UnresolvedImport
    1616from win32file import CloseHandle, FILE_GENERIC_READ, FILE_GENERIC_WRITE, FILE_FLAG_OVERLAPPED, FILE_ALL_ACCESS                 #@UnresolvedImport
    17 from win32pipe import CreateNamedPipe, ConnectNamedPipe, PIPE_ACCESS_DUPLEX, PIPE_READMODE_BYTE, PIPE_UNLIMITED_INSTANCES   #@UnresolvedImport
     17from win32pipe import CreateNamedPipe, ConnectNamedPipe, PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE, PIPE_READMODE_MESSAGE, PIPE_WAIT, PIPE_READMODE_BYTE, PIPE_UNLIMITED_INSTANCES   #@UnresolvedImport
    1818from win32api import error            #@UnresolvedImport
    1919from ntsecuritycon import SECURITY_CREATOR_SID_AUTHORITY, SECURITY_WORLD_SID_AUTHORITY, SECURITY_WORLD_RID, SECURITY_CREATOR_OWNER_RID    #@UnresolvedImport
    2020
     
    4747    def do_run(self):
    4848        while not self.exit_loop:
    4949            pipe_handle = self.CreatePipeHandle()
     50            log("CreatePipeHandle()=%s (waiting for connections)", pipe_handle)
    5051            try:
    5152                hr = ConnectNamedPipe(pipe_handle)
    5253                assert hr in (0, winerror.ERROR_PIPE_CONNECTED), "ConnectNamedPipe returned %i" % hr
     
    6768        sa = self.CreatePipeSecurityObject()
    6869        try:
    6970            return CreateNamedPipe(self.pipe_name,
    70                     PIPE_ACCESS_DUPLEX| FILE_FLAG_OVERLAPPED,
    71                     PIPE_READMODE_BYTE,
     71                    PIPE_ACCESS_DUPLEX, # | FILE_FLAG_OVERLAPPED,
     72                    PIPE_TYPE_MESSAGE | PIPE_WAIT, #PIPE_READMODE_BYTE,
    7273                    MAX_INSTANCES,
    7374                    0, 0, TIMEOUT, sa)
    7475        except Exception: