Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion cassandra/io/libevreactor.py
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,10 @@ def close(self):
msg = "Connection to %s was closed" % self.endpoint
if self.last_error:
msg += ": %s" % (self.last_error,)
self.error_all_requests(ConnectionShutdown(msg))
shutdown_exc = ConnectionShutdown(msg)
self.error_all_requests(shutdown_exc)
if not self.connected_event.is_set():
self.last_error = shutdown_exc
self.connected_event.set()

def handle_write(self, watcher, revents, errno=None):
Expand Down Expand Up @@ -378,6 +381,8 @@ def handle_read(self, watcher, revents, errno=None):
self.process_io_buffer()
else:
log.debug("Connection %s closed by server", self)
self.last_error = ConnectionShutdown(
"Connection to %s was closed by server" % self.endpoint)
self.close()
Comment on lines +384 to 386

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you set it unconditionally here, but guard it with if not self.connected_event.is_set(): in the other place?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in close, it guards against overwriting last_error when connection was closer before it was properly initialized, in handle_read it is just channeling error reason back to close, connection is already initialized at this point.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, but I don't get it :(
connected_event can be set in 4 places (for libevreactor at least, I didn't loo at others):

  1. defunct in connection.py, which calls close before setting the event.
  2. _handle_startup_response in case of ReadyMessage - successfull connection creation.
  3. _handle_auth_response in case of AuthSuccessMessage - successfull connection creation.
  4. close in libevreactor.py.

You said that you want to guard against overwriting error when connection was closed before properly initialized, but it looks to me like you are doing the opposite.
You are overwriting error only if event was not yet set. If it was not yet set then we didn't receive ReadyMessage or AuthSuccessMessage. We also can't be in defunct, because we are in if not self.is_defunct:, and also defunct calls close before setting event.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sylwiaszunejko since you approved the PR, maybe you understand this?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe I am wrong, but I understand it that way that if it was set by defunct or close we will not call handle_read anymore, so there is no other error that we would possible want to have here. In close if it was not yet set then we didn't receive ReadyMessage or AuthSuccessMessage, so the conn was not properly initialized as Dmitry said, or no?
I am now confused tbh

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok I think I get it. If the event is set in this check, it was set by either ReadyMessage (_handle_startup_response), or by AuthSuccessMessage (_handle_auth_response). In both of those cases the connection is properly initialized.
So the check looks correct - it will only set error if connection was not initialized yet.
I would love to better understand the paths that can trigger this, to verify that they don't set last_error already, but I won't hold this PR over that.


def push(self, data):
Expand Down
Loading