Skip to content

Commit

Permalink
moved the "simulate" --run-trigger code to actually execute inside th…
Browse files Browse the repository at this point in the history
…e child process usb_handler. This will make it a more accurate simulation, so we can catch bugs like the 'soft-shutdown' failing on MacOS because of a communication breakdown to the root_child, which can't access the unpickleable root_child['io'] variable from within the usb_handler child process

 * #73 (comment)
  • Loading branch information
maltfield committed Jun 15, 2023
1 parent 8f89dc1 commit 317fb73
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 31 deletions.
5 changes: 4 additions & 1 deletion src/buskill_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,11 +163,14 @@ def BusKillCLI( buskill_object ):
# did the user say that we should execute the trigger immediately on startup?
if args.run_trigger:
try:
bk.toggle()
bk.set_trigger( args.trigger )
confirm = input("Are you sure you want to execute the '" +str(bk.get_trigger())+ "' trigger RIGHT NOW? [Y/N] ")
if confirm.upper() in ["Y", "YES"]:
bk.simulate_hotplug_removal()

# wait until the asynchronous child process (that executes our
# trigger) exits
self.usb_handler.join()
else:
msg = "INFO: User chose not to execute trigger now. Exiting."
print( msg ); logger.info( msg )
Expand Down
2 changes: 1 addition & 1 deletion src/buskill_gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ def toggle_buskill(self):

# TODO: remove me after fixing bug https://github.com/BusKill/buskill-app/issues/73#issuecomment-1592195471
def check_root_child(self, dt):
msg = "DEBUG: bk.root_child:|" +str(self.bk.root_child)+ "|" )
msg = "DEBUG: bk.root_child:|" +str(self.bk.root_child)+ "|"
print( msg ); logger.debug( msg )

def switchToScreen( self, screen ):
Expand Down
65 changes: 36 additions & 29 deletions src/packages/buskill/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ def __init__(self):
self.ARM_FUNCTION = None
self.DISARM_FUNCTION = None
self.TRIGGER_FUNCTION = None
self.SIMULATE_HOTPLUG_REMOVAL = False

self.EXECUTED_AS_SCRIPT = None
self.LOG_FILE_PATH = logger.root.handlers[0].baseFilename
Expand Down Expand Up @@ -983,36 +984,13 @@ def hotplugCallbackNix( self, *argv ):
# simulates a fake hotplug removal event
def simulate_hotplug_removal( self ):

if self.OS_NAME_SHORT == 'lin' or self.OS_NAME_SHORT == 'mac':

self.simulate_hotplug_removal_nix()

elif self.OS_NAME_SHORT == 'win':

self.simulate_hotplug_removal_win()


# simulates a fake hotplug removal event on *nix platforms
def simulate_hotplug_removal_nix( self ):

# call the callback for hotplug events with 'simulation' for both 'context'
# and 'event'. The last argument is the constant signifying that the
# hotplug event is specifically a *removal* event
self.hotplugCallbackNix( 'simulation', 'simulation', usb1.HOTPLUG_EVENT_DEVICE_LEFT )
msg = "INFO: Arming & Simulating USB Removal Event"
print( msg ); logger.info( msg )

# TODO: test this. DBT_DEVICEREMOVALCOMPLETE may not be avaialble and so this
# may need to move wayy up (next to the actual hotplugCallbackWin() function's definition
def simulate_hotplug_removal_win( self ):

# call the callback for hotplug events with 'simulation' for 'hwnd',
# 'message', and 'lparam'. The second-to-last argument is the constant
# signifying that the hotplug event is specifically a *removal* event
self.hotplugCallbackWin(
'simulation',
'simulation',
DBT_DEVICEREMOVECOMPLETE,
'simulation'
)
# let the child process know that we don't need to wait for a USB removal
# event to call the trigger function
self.SIMULATE_HOTPLUG_REMOVAL = True
self.toggle()

####################
# ARMING FUNCTIONS #
Expand All @@ -1021,6 +999,15 @@ def simulate_hotplug_removal_win( self ):
# this works for both linux and mac
def armNix(self):

# are we just simulating this USB removal?
if self.SIMULATE_HOTPLUG_REMOVAL:
# we're simulating a removal event

# and 'event'. The last argument is the constant signifying that the
# hotplug event is specifically a *removal* event
self.hotplugCallbackNix( 'simulation', 'simulation', usb1.HOTPLUG_EVENT_DEVICE_LEFT )
return

with usb1.USBContext() as context:

if not context.hasCapability(usb1.CAP_HAS_HOTPLUG):
Expand Down Expand Up @@ -1049,6 +1036,26 @@ def armNix(self):

def armWin(self):

# are we just simulating this USB removal?
if self.SIMULATE_HOTPLUG_REMOVAL:
# we're simulating a removal event

# TODO: test this. DBT_DEVICEREMOVALCOMPLETE may not be avaialble and
# so this may need to move wayy up (next to the actual
# hotplugCallbackWin() function's definition

# call the callback for hotplug events with 'simulation' for 'hwnd',
# 'message', and 'lparam'. The second-to-last argument is the constant
# signifying that the hotplug event is specifically a *removal* event
self.hotplugCallbackWin(
'simulation',
'simulation',
DBT_DEVICEREMOVECOMPLETE,
'simulation'
)

return

w = Notification( self )
win32gui.PumpMessages()

Expand Down

0 comments on commit 317fb73

Please sign in to comment.