Skip to content

Commit

Permalink
resolved master outstation not able to shutdown gracefully
Browse files Browse the repository at this point in the history
  • Loading branch information
kefeimo committed Oct 30, 2022
1 parent 1fdf5ac commit d1ffdf9
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 21 deletions.
37 changes: 31 additions & 6 deletions src/dnp3_python/dnp3station/master_new.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ def __init__(self,
stale_if_longer_than: float = 2, # in seconds

stack_config=None,

# manager = asiodnp3.DNP3Manager(2, asiodnp3.ConsoleLogger().Create())
*args, **kwargs):
"""
TODO: docstring here
Expand Down Expand Up @@ -102,6 +104,7 @@ def __init__(self,
# init DNP3Manager(manager)
_log.debug('Creating a DNP3Manager.')
self.manager = asiodnp3.DNP3Manager(concurrencyHint, self.log_handler)
# self.manager = manager

# init TCPClient(channel)
_log.debug('Creating the DNP3 channel, a TCP client.')
Expand Down Expand Up @@ -471,7 +474,8 @@ def _get_updated_val_storage(self, gv_id: opendnp3.GroupVariationID) -> DbStorag

# Action: set polling attempt timestamp, set db value associated to gv_cls to None.
self.soe_handler.gv_last_poll_dict[gv_cls] = datetime.datetime.now()
self.soe_handler.gv_index_value_nested_dict[gv_cls] = None # Note: redundant, but explicitly define again.
self.soe_handler.gv_index_value_nested_dict[
gv_cls] = None # Note: redundant, but explicitly define again.

return {gv_cls: gv_db_val}

Expand Down Expand Up @@ -513,7 +517,7 @@ def get_db_by_group_variation_index(self, group: int, variation: int, index: int
"""Retrieve point value based on group-variation id, e.g., GroupVariationID(30, 6), and index
Return ret_val: DbStorage (return_meta=True, default), DbPointVal(return_meta=False)
EXAMPLE:
>>> # prerequisite: outstation db properly configured and updated, master_application properly initialized
>>> master_application.get_db_by_group_variation_index(group=6, variation=30, index=0)
Expand Down Expand Up @@ -569,9 +573,9 @@ def send_direct_point_command(self, group: int, variation: int, index: int, val_
config=config)

def send_select_and_operate_point_command(self, group: int, variation: int, index: int, val_to_set: DbPointVal,
call_back: Callable[[opendnp3.ICommandTaskResult], None] = None,
config: opendnp3.TaskConfig = None
) -> None:
call_back: Callable[[opendnp3.ICommandTaskResult], None] = None,
config: opendnp3.TaskConfig = None
) -> None:
"""
TODO: mimic send_direct_point_command
"""
Expand All @@ -582,10 +586,31 @@ def start(self):
self.master.Enable()

def shutdown(self):
# print("=======before master del self.__dict", self.__dict__)
"""
Execute an orderly shutdown of the Master.
The debug messages may be helpful if errors occur during shutdown.
Expected:
channel state change: SHUTDOWN
ms(1667103120775) INFO manager - Exiting thread (0)
Note:
Note: Don't use `self.manager.Shutdown()`, otherwise
"Process finished with exit code 134 (interrupted by signal 6: SIGABRT)"
Use `del self.master` instead of `self.master.Shutdown()`, otherwise
Process hanging
"""

sleep_before_master_shutdown = 2
_log.info(f"Master station shutting down in {sleep_before_master_shutdown} seconds...")
time.sleep(sleep_before_master_shutdown) # Note: hard-coded sleep to avoid hanging process
# del self.master
# self.master.Shutdown()
# self.channel.Shutdown()
#
# self.manager.Shutdown()

del self.slow_scan
del self.fast_scan
del self.master
Expand Down
28 changes: 13 additions & 15 deletions src/dnp3_python/dnp3station/outstation_new.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,26 +225,24 @@ def start(self):

def shutdown(self):
"""
Execute an orderly shutdown of the Outstation.
Execute an orderly shutdown of the Outstation.
The debug messages may be helpful if errors occur during shutdown.
The debug messages may be helpful if errors occur during shutdown.
Expected:
ms(1667102887814) INFO server - Operation aborted.
ms(1667102887821) INFO manager - Exiting thread (0)
Note:
Note: Don't use `self.manager.Shutdown()`, otherwise
Process finished with exit code 134 (interrupted by signal 6: SIGABRT)
"""
# TODO: cannot shut down: see Outstation and master hang on shutdown #1 at
# https: // github.com / ChargePoint / pydnp3 / issues / 1
time.sleep(2) # Note: hard-coded sleep to avoid hanging process
_outstation = self.get_outstation()
# _outstation.Shutdown()
del _outstation
del self.channel
del self.log_handler
del self.outstation_application
del self.stack_config
del self.command_handler
del self.listener
del self.retry_parameters
# del self.manager

self.manager.Shutdown() # Process finished with exit code 134 (interrupted by signal 6: SIGABRT)
# self.manager.__del__() # Process finished with exit code 134 (interrupted by signal 6: SIGABRT)
self.channel.Shutdown()

# self.manager.Shutdown()

@classmethod # TODO: Justify the necessity to use class method
def get_outstation(cls):
Expand Down

0 comments on commit d1ffdf9

Please sign in to comment.