Skip to content

Commit 0ffabf2

Browse files
committed
🔀 Merge branch 'synchronize-state_authenticated'
2 parents dc8004d + 400ac04 commit 0ffabf2

File tree

1 file changed

+24
-6
lines changed

1 file changed

+24
-6
lines changed

lib/net/imap.rb

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1116,8 +1116,8 @@ def tls_verified?; @tls_verified end
11161116
#
11171117
# Related: #logout, #logout!
11181118
def disconnect
1119+
in_logout_state = try_state_logout?
11191120
return if disconnected?
1120-
state_logout!
11211121
begin
11221122
begin
11231123
# try to call SSL::SSLSocket#io.
@@ -1131,11 +1131,15 @@ def disconnect
11311131
rescue Exception => e
11321132
@receiver_thread.raise(e)
11331133
end
1134-
@receiver_thread.join
11351134
synchronize do
11361135
@sock.close
11371136
end
1137+
@receiver_thread.join
11381138
raise e if e
1139+
ensure
1140+
# Try again after shutting down the receiver thread. With no reciever
1141+
# left to wait for, any remaining locks should be _very_ brief.
1142+
state_logout! unless in_logout_state
11391143
end
11401144

11411145
# Returns true if disconnected from the server.
@@ -3062,8 +3066,8 @@ def idle(timeout = nil, &response_handler)
30623066
raise @exception || Net::IMAP::Error.new("connection closed")
30633067
end
30643068
ensure
3069+
remove_response_handler(response_handler)
30653070
unless @receiver_thread_terminating
3066-
remove_response_handler(response_handler)
30673071
put_string("DONE#{CRLF}")
30683072
response = get_tagged_response(tag, "IDLE", idle_response_timeout)
30693073
end
@@ -3346,8 +3350,6 @@ def start_receiver_thread
33463350
rescue Exception => ex
33473351
@receiver_thread_exception = ex
33483352
# don't exit the thread with an exception
3349-
ensure
3350-
state_logout!
33513353
end
33523354
end
33533355

@@ -3429,6 +3431,8 @@ def receive_responses
34293431
@idle_done_cond.signal
34303432
end
34313433
end
3434+
ensure
3435+
state_logout!
34323436
end
34333437

34343438
def get_tagged_response(tag, cmd, timeout = nil)
@@ -3791,15 +3795,29 @@ def state_selected!
37913795
end
37923796

37933797
def state_unselected!
3794-
state_authenticated! if connection_state.to_sym == :selected
3798+
synchronize do
3799+
state_authenticated! if connection_state.to_sym == :selected
3800+
end
37953801
end
37963802

37973803
def state_logout!
3804+
return true if connection_state in [:logout, *]
37983805
synchronize do
3806+
return true if connection_state in [:logout, *]
37993807
@connection_state = ConnectionState::Logout.new
38003808
end
38013809
end
38023810

3811+
# don't wait to aqcuire the lock
3812+
def try_state_logout?
3813+
return true if connection_state in [:logout, *]
3814+
return false unless acquired_lock = mon_try_enter
3815+
state_logout!
3816+
true
3817+
ensure
3818+
mon_exit if acquired_lock
3819+
end
3820+
38033821
def sasl_adapter
38043822
SASLAdapter.new(self, &method(:send_command_with_continuations))
38053823
end

0 commit comments

Comments
 (0)