@@ -101,19 +101,6 @@ def __init__(
101
101
# Whether we are busy sending a fragmented message.
102
102
self .send_in_progress = False
103
103
104
- # Exception raised in recv_events, to be chained to ConnectionClosed
105
- # in the user thread in order to show why the TCP connection dropped.
106
- self .recv_exc : BaseException | None = None
107
-
108
- # Receiving events from the socket. This thread is marked as daemon to
109
- # allow creating a connection in a non-daemon thread and using it in a
110
- # daemon thread. This mustn't prevent the interpreter from exiting.
111
- self .recv_events_thread = threading .Thread (
112
- target = self .recv_events ,
113
- daemon = True ,
114
- )
115
- self .recv_events_thread .start ()
116
-
117
104
# Mapping of ping IDs to pong waiters, in chronological order.
118
105
self .pong_waiters : dict [bytes , tuple [threading .Event , float , bool ]] = {}
119
106
@@ -133,6 +120,21 @@ def __init__(
133
120
# Thread that sends keepalive pings. None when ping_interval is None.
134
121
self .keepalive_thread : threading .Thread | None = None
135
122
123
+ # Exception raised in recv_events, to be chained to ConnectionClosed
124
+ # in the user thread in order to show why the TCP connection dropped.
125
+ self .recv_exc : BaseException | None = None
126
+
127
+ # Receiving events from the socket. This thread is marked as daemon to
128
+ # allow creating a connection in a non-daemon thread and using it in a
129
+ # daemon thread. This mustn't prevent the interpreter from exiting.
130
+ self .recv_events_thread = threading .Thread (
131
+ target = self .recv_events ,
132
+ daemon = True ,
133
+ )
134
+
135
+ # Start recv_events only after all attributes are initialized.
136
+ self .recv_events_thread .start ()
137
+
136
138
# Public attributes
137
139
138
140
@property
0 commit comments