Test what happens when a break signal is sent during a waitforblockheight RPC call with a long timeout. Ctrl-Break is sent on Windows and SIGTERM is sent on other platforms, to trigger the same node shutdown sequence that would happen if Ctrl-C were pressed in a termi
(self)
| 271 | assert not custom_pidfile_absolute.exists() |
| 272 | |
| 273 | def break_wait_test(self): |
| 274 | """Test what happens when a break signal is sent during a |
| 275 | waitforblockheight RPC call with a long timeout. Ctrl-Break is sent on |
| 276 | Windows and SIGTERM is sent on other platforms, to trigger the same node |
| 277 | shutdown sequence that would happen if Ctrl-C were pressed in a |
| 278 | terminal. (This can be different than the node shutdown sequence that |
| 279 | happens when the stop RPC is sent.) |
| 280 | |
| 281 | The waitforblockheight call should be interrupted and return right away, |
| 282 | and not time out.""" |
| 283 | |
| 284 | self.log.info("Testing waitforblockheight RPC call followed by break signal") |
| 285 | node = self.nodes[0] |
| 286 | |
| 287 | if platform.system() == 'Windows': |
| 288 | # CREATE_NEW_PROCESS_GROUP prevents python test from exiting |
| 289 | # with STATUS_CONTROL_C_EXIT (-1073741510) when break is sent. |
| 290 | self.start_node(node.index, creationflags=subprocess.CREATE_NEW_PROCESS_GROUP) |
| 291 | else: |
| 292 | self.start_node(node.index) |
| 293 | |
| 294 | current_height = node.getblock(node.getbestblockhash())['height'] |
| 295 | |
| 296 | with ThreadPoolExecutor(max_workers=1) as ex: |
| 297 | # Call waitforblockheight with wait timeout longer than RPC timeout, |
| 298 | # so it is possible to distinguish whether it times out or returns |
| 299 | # early. If it times out it will throw an exception, and if it |
| 300 | # returns early it will return the current block height. |
| 301 | self.log.debug(f"Calling waitforblockheight with {self.rpc_timeout} sec RPC timeout") |
| 302 | fut = ex.submit(node.waitforblockheight, height=current_height+1, timeout=self.rpc_timeout*1000*2) |
| 303 | |
| 304 | self.wait_until(lambda: any(c["method"] == "waitforblockheight" for c in node.cli.getrpcinfo()["active_commands"])) |
| 305 | |
| 306 | self.log.debug(f"Sending break signal to pid {node.process.pid}") |
| 307 | if platform.system() == 'Windows': |
| 308 | # Note: CTRL_C_EVENT should not be sent here because unlike |
| 309 | # CTRL_BREAK_EVENT it can not be targeted at a specific process |
| 310 | # group and may behave unpredictably. |
| 311 | node.process.send_signal(signal.CTRL_BREAK_EVENT) |
| 312 | else: |
| 313 | # Note: signal.SIGINT would work here as well |
| 314 | node.process.send_signal(signal.SIGTERM) |
| 315 | node.process.wait() |
| 316 | |
| 317 | result = fut.result() |
| 318 | self.log.debug(f"waitforblockheight returned {result!r}") |
| 319 | assert_equal(result["height"], current_height) |
| 320 | node.wait_until_stopped() |
| 321 | |
| 322 | def init_empty_test(self): |
| 323 | self.log.info("Test that stopping and restarting a node that has done nothing is not causing a failure") |
no test coverage detected