Skip to content

Commit

Permalink
mavproxy.py: Clean up log_writer exit
Browse files Browse the repository at this point in the history
* Use threading.Event instead of daemon thread to avoid uncaught
  exception on ctrl+C exit
* Daemon threads are not recommended anymore

Signed-off-by: Ryan Friedman <[email protected]>
  • Loading branch information
Ryanf55 committed Dec 20, 2024
1 parent 5127953 commit dc3384d
Showing 1 changed file with 19 additions and 15 deletions.
34 changes: 19 additions & 15 deletions MAVProxy/mavproxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,8 @@ def __init__(self):
self.mav_error = 0
self.altitude = 0
self.last_distance_announce = 0.0
self.exit = False
# A newer thread event to stop MAVProxy
self.stop_event = threading.Event()
self.flightmode = 'MAV'
self.last_mode_announce = 0
self.last_mode_announced = 'MAV'
Expand Down Expand Up @@ -807,7 +808,7 @@ def process_stdin(line):
print("%-15s : %s" % (cmd, help))
return
if cmd == 'exit' and mpstate.settings.requireexit:
mpstate.status.exit = True
mpstate.status.stop_event.set()
return

if cmd not in command_map:
Expand Down Expand Up @@ -936,8 +937,12 @@ def mkdir_p(dir):

def log_writer():
'''log writing thread'''
while not mpstate.status.exit:
mpstate.logfile_raw.write(bytearray(mpstate.logqueue_raw.get()))
while not mpstate.status.stop_event.is_set():
if not mpstate.logqueue_raw.empty():
bytes = mpstate.logqueue_raw.get(block=False)
mpstate.logfile_raw.write(bytearray(bytes))

# TODO consider wait() the stop event instead
timeout = time.time() + 10
while not mpstate.logqueue_raw.empty() and time.time() < timeout:
mpstate.logfile_raw.write(mpstate.logqueue_raw.get())
Expand All @@ -948,6 +953,7 @@ def log_writer():
mpstate.logfile_raw.flush()



# If state_basedir is NOT set then paths for logs and aircraft
# directories are relative to mavproxy's cwd
def log_paths():
Expand Down Expand Up @@ -1009,18 +1015,17 @@ def open_telemetry_logs(logpath_telem, logpath_telem_raw):
stat = os.statvfs(logpath_telem)
if stat.f_bfree*stat.f_bsize < 209715200:
print("ERROR: Not enough free disk space for logfile")
mpstate.status.exit = True
mpstate.status.stop_event.set()
return

# use a separate thread for writing to the logfile to prevent
# delays during disk writes (important as delays can be long if camera
# app is running)
t = threading.Thread(target=log_writer, name='log_writer')
t.daemon = True
t.start()
except Exception as e:
print("ERROR: opening log file for writing: %s" % e)
mpstate.status.exit = True
mpstate.status.stop_event.set()
return


Expand Down Expand Up @@ -1121,7 +1126,7 @@ def main_loop():
set_stream_rates()

while True:
if mpstate is None or mpstate.status.exit:
if mpstate is None or mpstate.status.stop_event.is_set():
return

# enable or disable screensaver:
Expand Down Expand Up @@ -1218,12 +1223,12 @@ def main_loop():

def input_loop():
'''wait for user input'''
while mpstate.status.exit is not True:
while not mpstate.status.stop_event.is_set():
try:
line = mpstate.rl.input()
mpstate.input_queue.put(line)
except (EOFError, IOError):
mpstate.status.exit = True
not mpstate.status.stop_event.set()


def run_script(scriptfile):
Expand Down Expand Up @@ -1407,7 +1412,6 @@ def run_startup_scripts():

# global mavproxy state
mpstate = MPState()
mpstate.status.exit = False
mpstate.command_map = command_map
mpstate.continue_mode = opts.continue_mode
# queues for logging
Expand Down Expand Up @@ -1447,11 +1451,11 @@ def run_startup_scripts():

def quit_handler(signum=None, frame=None):
# print('Signal handler called with signal', signum)
if mpstate.status.exit:
if mpstate.status.stop_event.is_set():
print('Clean shutdown impossible, forcing an exit')
sys.exit(0)
else:
mpstate.status.exit = True
mpstate.status.stop_event.set()

# Listen for kill signals to cleanly shutdown modules
fatalsignals = [signal.SIGTERM]
Expand Down Expand Up @@ -1584,7 +1588,7 @@ def quit_handler(signum=None, frame=None):

# use main program for input. This ensures the terminal cleans
# up on exit
while (mpstate.status.exit is not True):
while (not mpstate.status.stop_event.is_set()):
try:
if opts.daemon or opts.non_interactive:
time.sleep(0.1)
Expand All @@ -1606,7 +1610,7 @@ def quit_handler(signum=None, frame=None):
m.init(mpstate)

else:
mpstate.status.exit = True
mpstate.status.stop_event.set()
sys.exit(1)

if opts.profile:
Expand Down

0 comments on commit dc3384d

Please sign in to comment.