RetroPie / EmulationStation

A Fork of Emulation Station for RetroPie. Emulation Station is a flexible emulator front-end supporting keyboardless navigation and custom system themes.
Other
863 stars 344 forks source link

EmulationStation does´t save metadata when you power off through gpio script #421

Open julenvitoria opened 6 years ago

julenvitoria commented 6 years ago

EmulationStation does´t save metadata when you launch a script to power off/reboot with a generic button connected to a gpio.This could be very interesting for many different projects, like bartops, gameboy zero, etc. It would also be interesting for anyone who had a system with a lot of roms because having so many roms is essential to make the list of favorites.

Thanks

pjft commented 6 years ago

Hi.

Realistically, what you're saying is effectively "ES doesn't save metadata if we kill the process".

I've seen plenty of threads in the forums about this specific situation and with some workaround scripts.

The only way this would be addressed at the root of the problem is if metadata would be saved on change rather than on exit.

I suppose that could be a fairly feasible change to the code and creating an option for that (as the "on exit" approach is more performant and is a good default for the majority of cases), but I'd rather have some perspective from the rest of the development group before considering implementing it as an option.

hex007 commented 6 years ago

@pjft Why dont we implement a SIGTERM signal handler to cleanly exit, saving metadata, which handles this issue??

On Linux, running processes receive Sigterm on shutdown being initiated. Sig handler would be really easy and concise to implement and maintain.

julenvitoria commented 6 years ago

@pjft Yes, there are many threads writing about this but with no lucky... the best working method was meleu’s at retropie’s forum but this method doesn’t work due to the last updates

@hex007 I'm trying this with an script killing ES first with pkill and it runs ok when you are in ES menu. The problem is when you are running an emulator... this needs to close the emulator first, close ES gracefully and then shutdown, in this order. For example this could be resolve saving metadata every emulator launch ( as @pjft wrote “saving on change rather than on exit”). I don’t know if it’s possible in some manner actually...

hex007 commented 6 years ago

Rant: Why are users shutting down directly from the Emulator. Have they never used a Computer ??

ES is in a suspended state when emulator is running. The alternative to handling this is to start emulator in a forked process and poll it regularly while also listening for the signal. This way when sigterm is received, it will gracefully exit.

julenvitoria commented 6 years ago

I’m with a GameBoy Zero project and, for example, this could be interesting if I build one with low-battery auto power off. In other cases it could be because of comfort... What is the use of a shutdown button through gpio if I have to turn off through the menu? 😅

Other question is that if I fork the processes it will need more resources and the resources are gold in raspberry.

flyinghead commented 6 years ago

SDL2 already installs signal handlers for SIGINT and SIGTERM, which post a SDL_QUIT event to the event queue, and ES exits cleanly. However, when running a game, SDL is de-initialized and these handlers are removed. Hence the issue when running an emulator. The other problem is SIGHUP, for which there's no handler by default. And I believe this is the signal received by ES when shutting down/powering off "normally" (i.e. sudo poweroff).

A simple solution is to install a signal handler for these 3 signals, which will make ES exit cleanly, regardless of whether an emulator is running or not. SDL will not install signal handlers for SIGINT or SIGTERM if one is already set.

hex007 commented 6 years ago

@pjft looks like we have a direction to work with

pjft commented 6 years ago

Thanks all for chiming in.

Just to clarify, the fact that we seem to have some sort of consensus on a technical approach here doesn't suggest that: a) it is the approach that'll be implemented; b) it will be done like proposed; c) it will be done soon;

At a personal level, I'm not especially thrilled with programming by exceptions, and this is exactly what it is. It also means that, should the user not want to save the gamelists because of something having gone wrong, the only real way out is to unplug the Pi.

I'm not sure, if you kill MAME or RetroArch, if the high-scores get saved, for instance (just an example, I don't really care much if they are as I fully understand if that's not the case), or why that would be standard expected behavior. I personally do not expect that a process does things when it's told to be killed - in fact, I appreciate that if a SIGTERM or SIGINT get issued, that the minimum needed operations to exit get executed.

I'm not sure I'd personally be keen on implementing such logic at the ES level, and would certainly appreciate some further thoughts from the other folks on the ES development side of things.

Don't take this as a rant, just as a personal point of view and a request for inputs from more informed people. I'd prefer for this to be - optionally - saved on change.

Thanks!

EDIT: just to make it clear, this is really a personal preference thing, hence my request for further inputs. I'm ultimately fine with whatever gets decided here, even though there's no promise or expectation for this.

csonsino commented 6 years ago

@julenvitoria I had a similar problem shutting down my RetroPie arcade cabinet from a GPIO button. I think that Emulationstation saves metadata on the kill signal, but you need to let it finish before rebooting/powering off. Here's my clean shutdown script that I execute on GPIO button press. I'm not sure if it saves all metadata, but it seems to save the favorites list:

#!/bin/bash

max_kill_wait_s=60

es_proc_name="emulationstation"

#es_pid=$(pgrep -f "${es_proc_name}")
es_pid=$(pidof "${es_proc_name}")
if [ -n "${es_pid}" ]; then
    # emulationstation is running

    echo "Stopping Emulationstation..."

    # stop emulationstation
    kill ${es_pid}

    i=1
    # wait for emulationstation to exit
    while [ -n "$(pgrep -f ${es_proc_name})" ] && [ $i -le $max_kill_wait_s ]
#    while [ -n "$(pidof ${es_proc_name})" ] && [ $i -le $max_kill_wait_s ]
    do
    echo -n "."
    sleep 1
    (( i++ ))
    done
    echo ""
fi

# power down
/usr/bin/sudo /sbin/poweroff