Skip to content

Commit

Permalink
Support for restart i3 reconnection.
Browse files Browse the repository at this point in the history
Search the socket path on reconnect if no user's socket_path defined.
  • Loading branch information
rysson committed Jun 21, 2022
1 parent 178a6be commit 85fe1f9
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 19 deletions.
10 changes: 7 additions & 3 deletions i3ipc/aio/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,7 @@ class Connection:
def __init__(self, socket_path: Optional[str] = None, auto_reconnect: bool = False, *,
display: Optional[str] = None):
self._socket_path = socket_path
self._connection_socket_path = None
self._auto_reconnect = auto_reconnect
self._pubsub = _AIOPubSub(self)
self._subscriptions = set()
Expand All @@ -297,7 +298,7 @@ def socket_path(self) -> str:
:rtype: str
"""
return self._socket_path
return self._connection_socket_path or self._socket_path

@property
def auto_reconect(self) -> bool:
Expand Down Expand Up @@ -393,8 +394,10 @@ async def connect(self) -> 'Connection':
if self._socket_path:
logger.info('using user provided socket path: {}', self._socket_path)

if not self._socket_path:
self._socket_path = await _find_socket_path(self._display)
if self._socket_path:
self._connection_socket_path = self._socket_path
else:
self._connection_socket_path = await _find_socket_path(self._display)

if not self.socket_path:
raise Exception('Failed to retrieve the i3 or sway IPC socket path')
Expand Down Expand Up @@ -428,6 +431,7 @@ async def do_reconnect():
error = None
break
except Exception as e:
self._connection_socket_path = None
error = e
await asyncio.sleep(0.001)

Expand Down
37 changes: 21 additions & 16 deletions i3ipc/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,24 +59,30 @@ def __init__(self, socket_path=None, auto_reconnect=False, display=None):

if socket_path:
logger.info('using user provided socket path: %s', socket_path)
else:
socket_path = self._find_socket_path()

if not socket_path:
raise Exception('Failed to retrieve the i3 or sway IPC socket path')

self.subscriptions = 0
self._pubsub = PubSub(self)
self._display = display
self._socket_path = socket_path
self._connection_socket_path = self._get_socket_path()
self._cmd_socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
self._cmd_socket.connect(self._socket_path)
self._cmd_socket.connect(self._connection_socket_path)
self._cmd_lock = Lock()
self._sub_socket = None
self._sub_lock = Lock()
self._auto_reconnect = auto_reconnect
self._quitting = False
self._synchronizer = None
self._display = display

def _get_socket_path(self):
"""Returns a current socket path."""
if self._socket_path:
socket_path = self._socket_path
else:
socket_path = self._find_socket_path()
if not socket_path:
raise Exception('Failed to retrieve the i3 or sway IPC socket path')
return socket_path

def _find_socket_path(self):
socket_path = os.environ.get("I3SOCK")
Expand Down Expand Up @@ -134,7 +140,7 @@ def socket_path(self) -> str:
:rtype: str
"""
return self._socket_path
return self._connection_socket_path

@property
def auto_reconnect(self) -> bool:
Expand Down Expand Up @@ -195,14 +201,13 @@ def _ipc_send(self, sock, message_type, payload):

def _wait_for_socket(self):
# for the auto_reconnect feature only
socket_path_exists = False
for tries in range(0, 500):
socket_path_exists = os.path.exists(self._socket_path)
if socket_path_exists:
break
self._connection_socket_path = self._get_socket_path()
if os.path.exists(self._connection_socket_path):
return True
time.sleep(0.001)

return socket_path_exists
return False

def _message(self, message_type, payload):
try:
Expand All @@ -213,13 +218,13 @@ def _message(self, message_type, payload):
raise e

logger.info('got a connection error, reconnecting', exc_info=e)
# XXX: can the socket path change between restarts?
# The socket path can change between restarts.
if not self._wait_for_socket():
logger.info('could not reconnect')
raise e

self._cmd_socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
self._cmd_socket.connect(self._socket_path)
self._cmd_socket.connect(self._connection_socket_path)
return self._ipc_send(self._cmd_socket, message_type, payload)
finally:
self._cmd_lock.release()
Expand Down Expand Up @@ -475,7 +480,7 @@ def _on(self, event: Union[Event, str], handler: Callable[['Connection', IpcBase

def _event_socket_setup(self):
self._sub_socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
self._sub_socket.connect(self._socket_path)
self._sub_socket.connect(self._connection_socket_path)

self._subscribe(self.subscriptions)

Expand Down

0 comments on commit 85fe1f9

Please sign in to comment.