@@ -4,7 +4,13 @@ use num_bigint::BigUint;
4
4
use num_traits:: FromPrimitive ;
5
5
use primitive_types:: U256 ;
6
6
use roles_logic_sv2:: utils:: Mutex ;
7
- use std:: { convert:: TryInto , net:: SocketAddr , ops:: Div , sync:: Arc , time} ;
7
+ use std:: {
8
+ convert:: TryInto ,
9
+ net:: SocketAddr ,
10
+ ops:: Div ,
11
+ sync:: { atomic:: AtomicBool , Arc } ,
12
+ time,
13
+ } ;
8
14
use tokio:: {
9
15
io:: { AsyncBufReadExt , AsyncWriteExt , BufReader } ,
10
16
net:: TcpStream ,
@@ -72,6 +78,7 @@ impl Client {
72
78
upstream_addr : SocketAddr ,
73
79
single_submit : bool ,
74
80
custom_target : Option < [ u8 ; 32 ] > ,
81
+ shutdown : Arc < AtomicBool > ,
75
82
) {
76
83
let stream = TcpStream :: connect ( upstream_addr) . await . unwrap ( ) ;
77
84
let ( reader, mut writer) = stream. into_split ( ) ;
@@ -105,19 +112,22 @@ impl Client {
105
112
106
113
// Reads messages sent by the Upstream from the socket to be passed to the
107
114
// `receiver_incoming`
115
+ let shutdown1 = shutdown. clone ( ) ;
108
116
task:: spawn ( async move {
109
117
let mut messages = BufReader :: new ( reader) . lines ( ) ;
110
- while let Ok ( message) = messages. next_line ( ) . await {
111
- match message {
112
- Some ( msg) => {
113
- if let Err ( e) = sender_incoming. send ( msg) . await {
114
- error ! ( "Failed to send message to receiver_incoming: {:?}" , e) ;
115
- break ; // Exit the loop if sending fails
118
+ while !shutdown1. clone ( ) . load ( std:: sync:: atomic:: Ordering :: Relaxed ) {
119
+ if let Ok ( message) = messages. next_line ( ) . await {
120
+ match message {
121
+ Some ( msg) => {
122
+ if let Err ( e) = sender_incoming. send ( msg) . await {
123
+ error ! ( "Failed to send message to receiver_incoming: {:?}" , e) ;
124
+ break ; // Exit the loop if sending fails
125
+ }
126
+ }
127
+ None => {
128
+ error ! ( "Error reading from socket" ) ;
129
+ break ; // Exit the loop on read failure
116
130
}
117
- }
118
- None => {
119
- error ! ( "Error reading from socket" ) ;
120
- break ; // Exit the loop on read failure
121
131
}
122
132
}
123
133
}
@@ -126,8 +136,9 @@ impl Client {
126
136
127
137
// Waits to receive a message from `sender_outgoing` and writes it to the socket for the
128
138
// Upstream to receive
139
+ let shutdown2 = shutdown. clone ( ) ;
129
140
task:: spawn ( async move {
130
- loop {
141
+ while !shutdown2 . load ( std :: sync :: atomic :: Ordering :: Relaxed ) {
131
142
let message: String = receiver_outgoing. recv ( ) . await . unwrap ( ) ;
132
143
( writer) . write_all ( message. as_bytes ( ) ) . await . unwrap ( ) ;
133
144
if message. contains ( "mining.submit" ) && single_submit {
@@ -166,39 +177,43 @@ impl Client {
166
177
// message to the Upstream node.
167
178
// Is a separate thread as it can be CPU intensive and we do not want to block the reading
168
179
// and writing of messages to the socket.
169
- std:: thread:: spawn ( move || loop {
170
- if miner_cloned. safe_lock ( |m| m. next_share ( ) ) . unwrap ( ) . is_ok ( ) {
171
- let nonce = miner_cloned. safe_lock ( |m| m. header . unwrap ( ) . nonce ) . unwrap ( ) ;
172
- let time = miner_cloned. safe_lock ( |m| m. header . unwrap ( ) . time ) . unwrap ( ) ;
173
- let job_id = miner_cloned. safe_lock ( |m| m. job_id ) . unwrap ( ) ;
174
- let version = miner_cloned. safe_lock ( |m| m. version ) . unwrap ( ) ;
175
- // Sends relevant candidate block header values needed to construct a
176
- // `mining.submit` message to the `receiver_share` in the task that is responsible
177
- // for sending messages to the Upstream node.
178
- if sender_share
179
- . try_send ( ( nonce, job_id. unwrap ( ) , version. unwrap ( ) , time) )
180
- . is_err ( )
181
- {
182
- warn ! ( "Share channel is not available" ) ;
183
- break ;
180
+ let shutdown3 = shutdown. clone ( ) ;
181
+ std:: thread:: spawn ( move || {
182
+ while !shutdown3. load ( std:: sync:: atomic:: Ordering :: Relaxed ) {
183
+ if miner_cloned. safe_lock ( |m| m. next_share ( ) ) . unwrap ( ) . is_ok ( ) {
184
+ let nonce = miner_cloned. safe_lock ( |m| m. header . unwrap ( ) . nonce ) . unwrap ( ) ;
185
+ let time = miner_cloned. safe_lock ( |m| m. header . unwrap ( ) . time ) . unwrap ( ) ;
186
+ let job_id = miner_cloned. safe_lock ( |m| m. job_id ) . unwrap ( ) ;
187
+ let version = miner_cloned. safe_lock ( |m| m. version ) . unwrap ( ) ;
188
+ // Sends relevant candidate block header values needed to construct a
189
+ // `mining.submit` message to the `receiver_share` in the task that is
190
+ // responsible for sending messages to the Upstream node.
191
+ if sender_share
192
+ . try_send ( ( nonce, job_id. unwrap ( ) , version. unwrap ( ) , time) )
193
+ . is_err ( )
194
+ {
195
+ warn ! ( "Share channel is not available" ) ;
196
+ break ;
197
+ }
184
198
}
199
+ miner_cloned
200
+ . safe_lock ( |m| m. header . as_mut ( ) . map ( |h| h. nonce += 1 ) )
201
+ . unwrap ( ) ;
185
202
}
186
- miner_cloned
187
- . safe_lock ( |m| m. header . as_mut ( ) . map ( |h| h. nonce += 1 ) )
188
- . unwrap ( ) ;
189
203
} ) ;
190
204
// Task to receive relevant candidate block header values needed to construct a
191
205
// `mining.submit` message. This message is contructed as a `client_to_server::Submit` and
192
206
// then serialized into json to be sent to the Upstream via the `sender_outgoing` sender.
193
207
let cloned = client. clone ( ) ;
208
+ let shutdown4 = shutdown. clone ( ) ;
194
209
task:: spawn ( async move {
195
210
tokio:: select!(
196
211
_ = recv_stop_submitting. changed( ) => {
197
212
warn!( "Stopping miner" )
198
213
} ,
199
214
_ = async {
200
215
let recv = receiver_share. clone( ) ;
201
- loop {
216
+ while !shutdown4 . load ( std :: sync :: atomic :: Ordering :: Relaxed ) {
202
217
let ( nonce, job_id, _version, ntime) = recv. recv( ) . await . unwrap( ) ;
203
218
if cloned. clone( ) . safe_lock( |c| c. status) . unwrap( ) != ClientStatus :: Subscribed {
204
219
continue ;
@@ -225,7 +240,7 @@ impl Client {
225
240
} ) ;
226
241
let recv_incoming = client. safe_lock ( |c| c. receiver_incoming . clone ( ) ) . unwrap ( ) ;
227
242
228
- loop {
243
+ while !shutdown . load ( std :: sync :: atomic :: Ordering :: Relaxed ) {
229
244
match client. clone ( ) . safe_lock ( |c| c. status ) . unwrap ( ) {
230
245
ClientStatus :: Init => panic ! ( "impossible state" ) ,
231
246
ClientStatus :: Configured => {
@@ -240,7 +255,7 @@ impl Client {
240
255
}
241
256
// Waits for the `sender_incoming` to get message line from socket to be parsed by the
242
257
// `Client`
243
- loop {
258
+ while !shutdown . load ( std :: sync :: atomic :: Ordering :: Relaxed ) {
244
259
if let Ok ( incoming) = recv_incoming. clone ( ) . recv ( ) . await {
245
260
Self :: parse_message ( client. clone ( ) , Ok ( incoming) ) . await ;
246
261
} else {
0 commit comments