@@ -338,41 +338,84 @@ def version(self):
338
338
return self ._pg_version
339
339
340
340
def _try_shutdown (self ,max_attempts ,with_force = False ):
341
+ assert type (max_attempts )== int # noqa: E721
342
+ assert type (with_force )== bool # noqa: E721
343
+ assert max_attempts > 0
344
+
341
345
attempts = 0
346
+
347
+ # try stopping server N times
348
+ while attempts < max_attempts :
349
+ attempts += 1
350
+ try :
351
+ self .stop ()
352
+ except ExecUtilException :
353
+ continue # one more time
354
+ except Exception :
355
+ eprint ('cannot stop node {}' .format (self .name ))
356
+ break
357
+
358
+ return # OK
359
+
360
+ # If force stopping is enabled and PID is valid
361
+ if not with_force :
362
+ return False
363
+
342
364
node_pid = self .pid
365
+ assert node_pid is not None
366
+ assert type (node_pid )== int # noqa: E721
343
367
344
- if node_pid > 0 :
345
- # try stopping server N times
346
- while attempts < max_attempts :
347
- try :
348
- self .stop ()
349
- break # OK
350
- except ExecUtilException :
351
- pass # one more time
352
- except Exception :
353
- eprint ('cannot stop node {}' .format (self .name ))
354
- break
355
-
356
- attempts += 1
357
-
358
- # If force stopping is enabled and PID is valid
359
- if with_force and node_pid != 0 :
360
- # If we couldn't stop the node
361
- p_status_output = self .os_ops .exec_command (cmd = f'ps -o pid= -p{ node_pid } ' ,shell = True ,ignore_errors = True ).decode ('utf-8' )
362
- if self .status ()!= NodeStatus .Stopped and p_status_output and str (node_pid )in p_status_output :
363
- try :
364
- eprint (f'Force stopping node{ self .name } with PID{ node_pid } ' )
365
- self .os_ops .kill (node_pid ,signal .SIGKILL ,expect_error = False )
366
- except Exception :
367
- # The node has already stopped
368
- pass
369
-
370
- # Check that node stopped - print only column pid without headers
371
- p_status_output = self .os_ops .exec_command (f'ps -o pid= -p{ node_pid } ' ,shell = True ,ignore_errors = True ).decode ('utf-8' )
372
- if p_status_output and str (node_pid )in p_status_output :
373
- eprint (f'Failed to stop node{ self .name } .' )
374
- else :
375
- eprint (f'Node{ self .name } has been stopped successfully.' )
368
+ if node_pid == 0 :
369
+ return
370
+
371
+ # TODO: [2025-02-28] It is really the old ugly code. We have to rewrite it!
372
+
373
+ ps_command = ['ps' ,'-o' ,'pid=' ,'-p' ,str (node_pid )]
374
+
375
+ ps_output = self .os_ops .exec_command (cmd = ps_command ,shell = True ,ignore_errors = True ).decode ('utf-8' )
376
+ assert type (ps_output )== str # noqa: E721
377
+
378
+ if ps_output == "" :
379
+ return
380
+
381
+ if ps_output != str (node_pid ):
382
+ __class__ ._throw_bugcheck__unexpected_result_of_ps (
383
+ ps_output ,
384
+ ps_command )
385
+
386
+ try :
387
+ eprint ('Force stopping node {0} with PID {1}' .format (self .name ,node_pid ))
388
+ self .os_ops .kill (node_pid ,signal .SIGKILL ,expect_error = False )
389
+ except Exception :
390
+ # The node has already stopped
391
+ pass
392
+
393
+ # Check that node stopped - print only column pid without headers
394
+ ps_output = self .os_ops .exec_command (cmd = ps_command ,shell = True ,ignore_errors = True ).decode ('utf-8' )
395
+ assert type (ps_output )== str # noqa: E721
396
+
397
+ if ps_output == "" :
398
+ eprint ('Node {0} has been stopped successfully.' .format (self .name ))
399
+ return
400
+
401
+ if ps_output == str (node_pid ):
402
+ eprint ('Failed to stop node {0}.' .format (self .name ))
403
+ return
404
+
405
+ __class__ ._throw_bugcheck__unexpected_result_of_ps (
406
+ ps_output ,
407
+ ps_command )
408
+
409
+ @staticmethod
410
+ def _throw_bugcheck__unexpected_result_of_ps (result ,cmd ):
411
+ assert type (result )== str # noqa: E721
412
+ assert type (cmd )== list # noqa: E721
413
+ errLines = []
414
+ errLines .append ("[BUG CHECK] Unexpected result of command ps:" )
415
+ errLines .append (result )
416
+ errLines .append ("-----" )
417
+ errLines .append ("Command line is {0}" .format (cmd ))
418
+ raise RuntimeError ("\n " .join (errLines ))
376
419
377
420
def _assign_master (self ,master ):
378
421
"""NOTE: this is a private method!"""