Commit edb427a8 authored by Martín Ferrari's avatar Martín Ferrari

Fix error in X11 forwarder when closing a connection; re-wrote to make it...

Fix error in X11 forwarder when closing a connection; re-wrote to make it clearer and better close connections
parent a5500c73
...@@ -815,67 +815,100 @@ def _spawn_x11_forwarder(server, xsock, xaddr): ...@@ -815,67 +815,100 @@ def _spawn_x11_forwarder(server, xsock, xaddr):
os._exit(1) os._exit(1)
def _x11_forwarder(server, xsock, xaddr): def _x11_forwarder(server, xsock, xaddr):
commr = {} toread = set([server])
commw = {} idx = {}
while(True): while(True):
toread = [x for x in commr.keys() if commr[x]["in"]] + [server] towrite = [x["wr"] for x in idx.values() if x["buf"]]
towrite = [x for x in commw.keys() if commw[x]["buf"]] assert all(map(lambda x: len(idx[idx[fd]["rd"]]["buf"]), towrite))
assert all(map(lambda x: idx[x]["rd"] == x, idx))
assert all(map(lambda x: idx[idx[x]["wr"]]["wr"] == x, idx))
(rr, wr, er) = select.select(toread, towrite, []) (rr, wr, er) = select.select(toread, towrite, [])
if server in rr: if server in rr:
xconn = socket.socket(*xsock) xconn = socket.socket(*xsock)
xconn.connect(xaddr) xconn.connect(xaddr)
client, addr = server.accept() client, addr = server.accept()
commr[xconn.fileno()] = commw[client.fileno()] = { toread.add(client)
"in": xconn, toread.add(xconn)
"out": client, idx[client] = {
"buf": []} "rd": client,
commw[xconn.fileno()] = commr[client.fileno()] = { "wr": xconn,
"in": client, "buf": [],
"out": xconn, "closed": False
"buf": []} }
idx[xconn] = {
"rd": xconn,
"wr": client,
"buf": [],
"closed": False
}
continue continue
for fd in rr: for fd in rr:
chan = idx[fd]
try: try:
s = os.read(fd, 4096) s = os.read(fd.fileno(), 4096)
except OSError, e: except OSError, e:
if e.errno != errno.EINTR: if e.errno != errno.EINTR:
raise raise
if s == "":
continue continue
if s == "": if s == "":
# fd closed # fd closed
#commr[fd]["in"].shutdown(socket.SHUT_RD) toread.remove(fd)
if not commr[fd]["buf"]: chan["closed"] = True
commr[fd]["out"].shutdown(socket.SHUT_WR) if not chan["buf"]:
commr[fd]["in"] = None # close the writing side
try:
chan["wr"].shutdown(socket.SHUT_WR)
except:
pass # might fail sometimes
else: else:
commr[fd]["buf"].append(s) chan["buf"].append(s)
for fd in wr: for fd in wr:
chan = idx[idx[fd]["wr"]]
try: try:
x = os.write(fd, commw[fd]["buf"][0]) x = os.write(fd.fileno(), chan["buf"][0])
except OSError, e: except OSError, e:
if e.errno == errno.EINTR: if e.errno == errno.EINTR:
if x > 0:
pass
else:
continue continue
if e.errno != errno.EPIPE: if e.errno != errno.EPIPE:
raise raise
# broken pipe, discard output and close # broken pipe, discard output and close
commw[fd]["in"].shutdown(socket.SHUT_RD) try:
commw[fd]["out"].shutdown(socket.SHUT_WR) chan["rd"].shutdown(socket.SHUT_RD)
del commr[commw[fd]["in"].fileno()] chan["wr"].shutdown(socket.SHUT_WR)
del commw[fd] except:
pass
toread.remove(chan["rd"])
chan["closed"] = 1
chan["buf"] = None
continue continue
if x < len(commw[fd]["buf"][0]): if x < len(chan["buf"][0]):
commw[fd]["buf"][0] = commw[fd]["buf"][0][x:] chan["buf"][0] = chan["buf"][x:]
else: else:
del commw[fd]["buf"][0] del chan["buf"][0]
if not commw[fd]["buf"] and not commw[fd]["in"]: if not chan["buf"] and chan["closed"]:
commw[fd]["out"].shutdown(socket.SHUT_WR) chan["wr"].shutdown(socket.SHUT_WR)
del commw[fd]["out"] chan["buf"] = None
# clean-up
for chan in idx.values():
if chan["rd"] not in idx:
# already deleted
continue
twin = idx[chan["wr"]]
if not chan["closed"] or chan["buf"] or not twin["closed"] \
or twin["buf"]:
continue
try:
chan["rd"].close()
except:
pass
try:
chan["wr"].close()
except:
pass
del idx[chan["rd"]]
del idx[chan["wr"]]
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment