diff options
author | Arksine <arksine.code@gmail.com> | 2020-08-08 15:04:55 -0400 |
---|---|---|
committer | KevinOConnor <kevin@koconnor.net> | 2020-08-11 10:47:04 -0400 |
commit | bf221d5e26814055f654e0f3144f79af3954e5d4 (patch) | |
tree | ee202d1853fb88f8fe3f5cdab37e9f6214f45b50 | |
parent | 4dcf494b9725bd3cc3d2d59d9855f5afca460f7b (diff) | |
download | kutter-bf221d5e26814055f654e0f3144f79af3954e5d4.tar.gz kutter-bf221d5e26814055f654e0f3144f79af3954e5d4.tar.xz kutter-bf221d5e26814055f654e0f3144f79af3954e5d4.zip |
webhooks: Implement a send buffer for socket writes
This prevents ClientConnection.send() from blocking, removing the possibility that callers become reentrant.
Signed-off-by: Eric Callahan <arksine.code@gmail.com>
-rw-r--r-- | klippy/webhooks.py | 54 |
1 files changed, 29 insertions, 25 deletions
diff --git a/klippy/webhooks.py b/klippy/webhooks.py index 9f4fa5bf..97a4c45d 100644 --- a/klippy/webhooks.py +++ b/klippy/webhooks.py @@ -158,8 +158,8 @@ class ClientConnection: self.sock = sock self.fd_handle = self.reactor.register_fd( self.sock.fileno(), self.process_received) - self.partial_data = "" - self.mutex = self.reactor.mutex() + self.partial_data = self.send_buffer = "" + self.is_sending_data = False logging.info( "webhooks: New connection established") @@ -222,30 +222,34 @@ class ClientConnection: self.send({'method': "response", 'params': result}) def send(self, data): - with self.mutex: - retries = 10 - data = json.dumps(data) + "\x03" - while data: - try: - sent = self.sock.send(data) - except socket.error as e: - if e.errno == errno.EBADF or e.errno == errno.EPIPE \ - or not retries: - sent = 0 - else: - retries -= 1 - waketime = self.reactor.monotonic() + .001 - self.reactor.pause(waketime) - continue - retries = 10 - if sent > 0: - data = data[sent:] + self.send_buffer += json.dumps(data) + "\x03" + if not self.is_sending_data: + self.is_sending_data = True + self.reactor.register_callback(self._do_send) + + def _do_send(self, eventtime): + retries = 10 + while self.send_buffer: + try: + sent = self.sock.send(self.send_buffer) + except socket.error as e: + if e.errno == errno.EBADF or e.errno == errno.EPIPE \ + or not retries: + sent = 0 else: - logging.info( - "webhooks: Error sending server data," - " closing socket") - self.close() - break + retries -= 1 + waketime = self.reactor.monotonic() + .001 + self.reactor.pause(waketime) + continue + retries = 10 + if sent > 0: + self.send_buffer = self.send_buffer[sent:] + else: + logging.info( + "webhooks: Error sending server data, closing socket") + self.close() + break + self.is_sending_data = False class WebHooks: def __init__(self, printer): |