ensuring ES gracefully finish and save metadata in every system shutdown
-
@hex said in ensuring ES gracefully finish and save metadata in every system shutdown:
Would it be more useful to have the script that handles safe shutdown signal ES that the System is going down and it should perform cleanup. Another option would be to have a service that handles the MD saving only and let it handle the clean shutdown.
eh... pretty much what this whole thread is all about. :D
-
I have some new information for you.
After doing a bit of research, I tried to test out the killes service. If I SSH into a terminal session and run "sudo systemctl stop killes" while the killes service is running, EmulationStation will quit. The next time I start up EmulationStation, the metadata was saved correctly.
So the service does work, and IS invoking the shell script to kill EmulationStation when the service stops. However, it seems that the service is stopping AFTER EmulationStation is already killed. For reference, I updated my RetroPie install along with the kernel tonight to see if it would help.
-
@meleu said in ensuring ES gracefully finish and save metadata in every system shutdown:
@dankcushions You just gave me an idea for a feature request: an option on the ES menu to Save Current Metadata (something like the "Save Current Configuration" on RetroArch) Then a careful user can do it to prevent loss of data.
My suggestion for such option: in the OPTIONS menu (the one that appears when the users press Select).
@Zigurana @Hex @pjft @jdrassa and other ES hackers, do you guys think it's feasible?
doesn't restarting emulationstation accomplish the same goal? seems like a redundant option to me.
-
@dankcushions
I totally agree, most of these "errors" seems to be somehow user made. The service should work and if somehow the power is cut then it's a hardware error and not software.@meleu
The only thing that can be improved imho is the emulator detection routine. The detection of ES PID is done 100% and I think there is no more improvement to do in ES itself. The ES restart via options menu is exactly the feature you mentioned. -
@cyperghost said in ensuring ES gracefully finish and save metadata in every system shutdown:
The detection of ES PID is done 100%
This is as good a time as any to thank you guys for putting this together. I dual boot between RetroPie and OSMC and a while back I used part of this to create a script that launches from the ES Kodi system menu that allows ES to shut down and save all MD properly before rebooting into OSMC. This was a very welcome addition after the update to 'favorites', 'last played', etc. Very keen and thanks again.
-
@mediamogul quick side note here if I may: what were the broad steps you followed to build your OSMC dual boot? I have Kodi setup, but I really do prefer the OSMC flavor. Always have.
-
NOOBS was used for the setup I'm currently using. Since both sides will need to be redone for Stretch, I plan to use PINN to replace it in the months to come, as it offers RetroPie as one of it's default install options. As you may be aware, using NOOBS for this involves converting a RetroPie SD image to be used. After that, it's just a matter of booting it up and selecting RetroPie to install alongside the already available OSMC option.
When it's all said and done, you either have the option of using a dual boot selection screen every time the Pi starts, or you can take a page out of the Multi Boot Pi book like I do and use a custom addon for Kodi that launches RetroPie, along with a custom script in RetroPie to return to OSMC. All that said, besides mentioning PINN as an option, I'm probably burying the lead in that you could just get an install image from the Multiboot Pi page with OSMC and RetroPie already configured for this. While it will install older versions of both, they can of course be updated independently as they would normally.
-
@meleu I am still not able to get the metadata to save from my process. Is there something I could look at to help troubleshoot the issue.
I have verified that the killes.service is enabled and therefore running.
I can execute the killes.sh script from the command line and emulation station processes do terminate. After I power down and backup, the metadata has been saved.
My issue is when I execute the 'shutdown' command from within emulation station as a menu item. The command performed is the 'shutdown now' command, but the meta data is never saved when I execute it this way.
Any thoughts that would help me debug would be great.
-
Any updates on the MD not saving?
I've made no progress. MD only saves when performing shutdowns or restarts within ES menu....not button :/
-
I just wanted to update my previous post as I did not include the proper information before. I am running Retropie v4.3, RPi3 Model B, 5v @2.5A PSU, 32GB SandDisk Microsd.
I have installed the killes service and installed the killes.sh script. I can successfully save metadata by running the script from the command line. I cannot save metadata if I run a script that does the 'shutdown now' command which is executed from the main retropie menu as was posted here: https://retropie.org.uk/forum/topic/10736/power-on-off-option-in-main-menu/3
Additionally how do you put your system information into a footer in your post
-
Hi! I´m on your previous situation: Modded Nespi Case soft shutdown, following PDF (working GREAT) and after some iso backups, I installed the killes.sh, but is not working... adding some favs and pressing power down button, and after power it up, favs didn´t save.
I can see killes.service enabled from :~ $ systemctl status killes
● killes.service - Kill EmulationStation
Loaded: loaded (/etc/systemd/system/killes.service; enabled)
Active: active (exited) since Sat 2018-03-24 10:05:18 UTC; 3min 46s agoIs the fresh install your only way to go? For me, it would be a nightmare re-install 30gb of roms and ports, gamepad config, overclock... I´m making backups every now and then just to not repeat what it´s done (like 6 months of work here)
So... how can I emulate the "fresh install" on my scripts? is something I should wipe from systemctl or something?
Thank you!
-
@bananu
Sorry man, I really don't know what is causing this issue for people. Especially because the killes script worked for me both on a system I had already set up completely, and with a fresh install. Wish I could be more of a help here... -
@meleu HI! I'm trying to make the gracefully finish to work but I can't and I don't know why... I follow all the steps even create the script in the same path than you (/etc) but it does not work. I'm using a raspberry pi 3 with the last version of retropie and shutdown script with a button connected to GPIO 3. Could you guide me about this?
Thanks -
When using this with the Kintaro 9000 case, the power switch doesn't respond but the reset switch does. Using the reset switch won't save metadata. If anyone has experience with this, I'd love some help.
Pi Model or other hardware: Pi 3b
Power Supply used: 5.1v 2.5a
RetroPie Version Used: 4.3.17
Built From: Pre made SD Image on RetroPie website, updated to 4.3.17
USB Devices connected: dongle for wireless keyboard
Controller used: Official PS3 Controller
How to replicate the problem: Followed install instructions from Kintaro 9000, then followed instructions in this post -
Hello fellows,
I've just updated the OP with the following warning:
UPDATE: many guys are reporting that this trick isn't working anymore. Maybe something has changed after an OS update, but I'm not sure. I don't use GPIO buttons to shutdown my RetroPie myself.
I'm currently very busy on other projects and unable to provide support here. Sorry mates..
-
Ok, thanks for the reply!!
-
@meleu said in ensuring ES gracefully finish and save metadata in every system shutdown:
Hello fellows,
I've just updated the OP with the following warning:
UPDATE: many guys are reporting that this trick isn't working anymore. Maybe something has changed after an OS update, but I'm not sure. I don't use GPIO buttons to shutdown my RetroPie myself.
I'm currently very busy on other projects and unable to provide support here. Sorry mates..
Much appreciated for the update and continued hard work. I'll be following along :)
-
Look this script, is working for me
https://github.com/RetroFlag/retroflag-picase -
@finaluser Yes yes... the
killall
method ;) It's the simpelest method and it will fail if there are emulators running in background.The service @meleu gots following reason. You don't need annother script that explicitly shutdowns emulationstation. Sadly the service seems to not run correctly anymore (users reports that)
So I recreated annother script Multi Switch Shutdown Script that suppots all NESPicases, the Pimoroni ONOFFSHIM, the Mausberry and any generic button.
It will correctly shutdown emulators and ES and the reset button works more as an reset button ;) It shutdowns emulators if there are any running. Or it just restart ES if you are in main menu. The reboot option can be done by menu or via command line ;)
-
@meleu, I recently set up a safe-shutdown script for my Super Kuma 9000 case, and I ended up using a patchwork of your code, @cyperghost's, and @mediamogul's. It all seems to be running cleanly now, at least on my system - I tested shutdowns, resets, and full system reboots both from within Emulator Station and within a game, and it seems to be saving metadata correctly in all instances.
I hope this is useful to you or others who come across this thread!
I wrote it specifically to work with my modified kintaro
pcb.py
script, included at the end of this post. Though you should be able to call it from anywhere, as long as you pass it the appropriate option (default is REBOOT):- --SHUTDOWN - Initiates a clean shutdown of any open emulators, then Emulation Station, and finally the Pi itself
- --REBOOT - Initiates a clean shutdown of any open emulators, then Emulation Station, and finally reboots the Pi
- --RESET - Initiates a clean shutdown of any open emulators, then a clean restart of Emulation Station. If Emulation Station is not open (ie, you crashed to the terminal somehow), this option will restart it.
Hopefully it's not too janky, I'm beyond rusty with bash and python.
TicTac's
killes.sh
code#!/bin/bash # Meleu's Graceful Shutdown code, with improvements from mediamogul and cyberghost. # Hacked together by TicTac, and further tweaked to work with his Kintaro control script. # Set the mode of the script. Options are --SHUTDOWN, --RESET (only restarts ES), and --REBOOT MODE="REBOOT" # Default to system reboot if [ $1 ]; then # If we got an option, use it key="$1" case $key in --SHUTDOWN) MODE="SHUTDOWN" ;; --RESET) MODE="RESET" ;; --REBOOT) MODE="REBOOT" ;; esac fi # New PID code lifted from cyperghost's Multi Switch Shutdown Script # If there's an emulator running, we need to kill it and go back to ES EMUPID="$(pgrep -f -n runcommand.sh)" if [[ -n "$EMUPID" ]]; then pkill -P "$(echo $EMUPID | tr ' ' ',')" kill "$EMUPID" # Hold in this while loop until the emulator process stops while s=$(ps -p "$EMUPID" -o s=) && [ "$s" ] && [ "$s" != 'Z' ]; do sleep 1 done fi ESPID="$(pgrep -f "/opt/retropie/supplementary/.*/emulationstation([^.]|$)")" if [ -n "$ESPID" ]; then # If ES was running... # Touch appropriate file to trigger ES reset/reboot/shutdown, then kill the ES Process case $MODE in SHUTDOWN) sudo touch /tmp/es-shutdown && chown pi:pi /tmp/es-shutdown && kill $ESPID ;; RESET) sudo touch /tmp/es-restart && chown pi:pi /tmp/es-restart && kill $ESPID ;; REBOOT) sudo touch /tmp/es-sysrestart && chown pi:pi /tmp/es-sysrestart && kill $ESPID ;; esac while s=$(ps -p "$ESPID" -o s=) && [ "$s" ] && [ "$s" != 'Z' ]; do sleep 1 done sleep 1 else # If it wasn't, directly shutdown / reboot the pi or restart ES case $MODE in SHUTDOWN) sudo shutdown -h now ;; RESET) emulationstation ;; REBOOT) sudo shutdown -r now ;; esac sleep 1 fi sleep 1
TicTac's
/opt/kintaro/pcb.py
code#!/usr/bin/python3 -u #Copyright 2017 Michael Kirsch #Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), #to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: #The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. ###################### # MODIFIED BY TICTAC # ###################### # I stripped out the fan control functionality (it's not used in my build), and am working to make shutdowns / resets safe for Emulation Station. # # WIP Log: # 180525 - Stripped out the fan control code with little issues. Modified reset switch to indicate when it's changing functionality # - and to be generally less shitty # 180526 - Replaced old code for shutdowns and resets (just calls to sudo shutdown) with appropriate calls to /opt/kintaro/killes.sh # - Also further tweaked reset button functionality. Tapping reset will restart Emulation Station, holding it for 1-5seconds # - will reboot the system, and holding it for 5+seconds will cancel it. System seems to be stable now, no metadata is getting # - lost on shutdowns or resets from within a game, or just emulation station itself. import http.server import configparser import time import os import RPi.GPIO as GPIO import subprocess from configparser import SafeConfigParser from enum import Enum pcb_components={"LED":7,"FAN":8,"RESET":3,"POWER":5,"CHECK_PCB":10} class path(): kintaro_folder = "/opt/kintaro/" start_folder = "start/" intro_video = kintaro_folder + start_folder + "intro.mp4" # DELETE? config_file = kintaro_folder + start_folder + "kintaro.config" temp_command = 'vcgencmd measure_temp' class vars(): reset_hold_short = 10 reset_hold_long = 50 debounce_time = 0.01 counter_time = 0.1 GPIO.setmode(GPIO.BOARD) #Use the same layout as the pins GPIO.setup(pcb_components["LED"], GPIO.OUT) #LED Output GPIO.setup(pcb_components["FAN"], GPIO.OUT) #FAN Output # DELETE? GPIO.setup(pcb_components["POWER"], GPIO.IN) #set pin as input GPIO.setup(pcb_components["RESET"], GPIO.IN, pull_up_down=GPIO.PUD_UP) #set pin as input and switch on internal pull up resistor GPIO.setup(pcb_components["CHECK_PCB"], GPIO.IN, pull_up_down=GPIO.PUD_UP) def temp(): #returns the gpu temoperature res = os.popen(path.temp_command).readline() return float((res.replace("temp=", "").replace("'C\n", ""))) class led: #class to control the led def toggle(status): #toggle the led on of off if status == 0: #the led is inverted GPIO.output(pcb_components["LED"], GPIO.LOW) if status == 1: GPIO.output(pcb_components["LED"], GPIO.HIGH) def blink(amount,interval): #blink the led for x in range(amount): led.toggle(1) time.sleep(interval) led.toggle(0) time.sleep(interval) def return_config_bool(searchterm): Config = configparser.ConfigParser() Config.read(path.config_file) # read the configfile return Config.getboolean("Boot", searchterm) if return_config_bool("video"): # DELETE? os.system("omxplayer " + path.intro_video + " &") #start the bootvideo on start def toggle(toggle_this): #change one of the values in the config file parser = configparser.ConfigParser() parser.read(path.config_file) if return_config_bool(toggle_this): parser.set('Boot', toggle_this, "False") else: parser.set('Boot', toggle_this, "True") with open(path.config_file, "w+") as configfile: parser.write(configfile) def Falling_Power(channel): if (GPIO.input(pcb_components["POWER"]) == GPIO.HIGH) and (GPIO.input(pcb_components["CHECK_PCB"]) == GPIO.LOW): # shutdown function if the powerswitch is toggled led.toggle(0) os.system("sudo bash /opt/kintaro/killes.sh --SHUTDOWN") # Flag system for shutdown and initiate killes.sh def Falling_Reset(channel): if (GPIO.input(pcb_components["RESET"]) == GPIO.LOW): # sanity check to make sure Reset switch is actually toggled reset_counter = 0 # counter for while loops reset_stage = 0 # stage toggle for reset functionality time.sleep(vars.debounce_time) # debounce time while (GPIO.input(pcb_components["RESET"]) == GPIO.LOW): # Count up until we hit the first cutoff if reset_counter == vars.reset_hold_short: # Check if we're at the first cutoff reset_stage = 1 led.blink(1, 0.2) # Blink to indicate reset stage has changed led.toggle(1) if reset_counter == vars.reset_hold_long: # Check if we're at the second cutoff reset_stage = 2 led.blink(2, 0.2) # Blink to indicate reset stage has changed again led.toggle(1) reset_counter = reset_counter + 1 time.sleep(vars.counter_time) if reset_stage == 0: os.system("sudo bash /opt/kintaro/killes.sh --RESET") elif reset_stage == 1: os.system("sudo bash /opt/kintaro/killes.sh --REBOOT") else: # DO NOTHING. THIS STAGE IS IN CASE YOU ACCIDENTALLY HIT THE BUTTON led.blink(3, 0.2) led.toggle(1) def PCB_Pull(channel): GPIO.cleanup() if (GPIO.input(pcb_components["POWER"]) == GPIO.HIGH) and GPIO.input(pcb_components["CHECK_PCB"]) == GPIO.LOW: # What the hell is this for? os.system("sudo bash /opt/kintaro/killes.sh --SHUTDOWN") # Flag system for shutdown and initiate killes.sh GPIO.add_event_detect(pcb_components["CHECK_PCB"],GPIO.RISING,callback=PCB_Pull) time.sleep(1) if return_config_bool("pcb") and GPIO.input(pcb_components["CHECK_PCB"])==GPIO.LOW: #check if there is an pcb and if there is then attach the interrupts led.toggle(1) GPIO.add_event_detect(pcb_components["RESET"], GPIO.FALLING, callback=Falling_Reset) GPIO.add_event_detect(pcb_components["POWER"], GPIO.FALLING, callback=Falling_Power) #check for interrupts :D while True: time.sleep(5) led.toggle(1)
Contributions to the project are always appreciated, so if you would like to support us with a donation you can do so here.
Hosting provided by Mythic-Beasts. See the Hosting Information page for more information.