Menu

#1729 Rosegarden normal exit with respect to SIGTERM

None
open
nobody
None
5
2025-07-14
2025-07-07
musewhirl
No

This could easily be more of a feature than a bug. It's worth mentioning only in the line of "tidy shutdown". RG considers all of the following to be a "normal exit", as it actually says in its logs. There may be others, but these I've used often:

  • CTRL-Q
  • Close via the window "x" icon
  • ALT-F4

The following log entry appears shortly afterwards:

[AudioPlayQueue] This tends to be the last thing you'll see on a normal exit.

And furthermore, with JACK transport active, nothing appears in the JACK log via its default loglevel. All nice and neat.

I had reason to shutdown RG from the command line without accessing its interface...nothing had been edited. I thought that a SIGTERM along with PID would work based on its definition i.e. a "request to terminate". According to Wikipedia:

SIGTERM
The SIGTERM signal is sent to a process to request its termination. Unlike the SIGKILL signal, it can be caught and interpreted or ignored by the process. This allows the process to perform nice termination releasing resources and saving state if appropriate. SIGINT is nearly identical to SIGTERM.

NB: it can be ignored, which I think is happening and if that is not the intent or something went wrong, then this is a bug. Of course SIGTERM only makes sense if there is also nothing to save, in which case SIGKILL with no neat shutdown follows. On the other hand this is all an edge case, so maybe SIGTERM was intentionally ignored i.e. "the interface is there...use it!".

Just as an FYI, other signals do not provide a graceful termination (not one I can find anyway)...you might as well just SIGKILL, and as you know that roughly translates to "die! Die!! DIE!!!"...not exactly a request, but RG complies like any other process. And you end up with no entry in the logs about anything. And on top of that even JACK complains on RG's behalf, even though RG was doing nothing with JACK at the time:

JackEngine::XRun: client = rosegarden was not finished, state = Triggered
JackAudioDriver::ProcessGraphAsyncMaster: Process error

It looks like standard XRun, but it's not...For a normal exit, nothing shows up in JACK as mentioned above. I assume that whatever resources RG had opened will hang around there and hopefully be dealt with by JACK.

There may be other scenarios where the window manager or OS ask RG to close as nicely as it can "or else", so perhaps having it try might might sense, if it doesn't over complicate the code. Anyway, I think the above was worth mentioning.

Discussion

  • Ted Felix

    Ted Felix - 2025-07-10

    I tried gnome-text-edit and libreoffice writer. Sending a SIGTERM to either of them just closes them immediately, even if you were in the middle of something. gnome-text-edit is kind enough to restore what you were doing on re-launch. Writer is not.

    We have no code in place to handle SIGTERM specifically, although there is a signal handler in place for SIGUSR1. No idea why. Something about pipes. See RosegardenMainWindow::installSignalHandlers().

    So it seems like we fall within the range of reasonable and typical behavior.

    I think it was Will (@abrolag) who at one time had asked for better handling of an unceremonious shutdown of rg. Logging out while rg was up on a Raspberry Pi? Perhaps we could install a SIGTERM handler and have it at least do an autosave? Looks pretty easy to do. Anyone interested?

     
  • musewhirl

    musewhirl - 2025-07-10

    Well, if it will help, here's the full story of how I ran into the problem. And it will give me a chance to point out another ugly I should have mentioned earlier.

    Until recently, I had never had any reason to use the command line feature with a filepath to launch RG and hence save the time opening a file manager, locating the file...blah, blah, blah. I decided to try it, and it worked great. I had RG up and running in a terminal...in the foreground. I then CTRL-C out to try a few more sessions. Alas, when I happened to open the file manager, every single session I opened had a lock file hanging around :-( Fortunately, when opened normally, RG just cleaned each one up (or reused them)...no issue. I manually deleted all the other lock files I had visited rather than chase them with RG's interface. I was not sure if they would trigger a crash recovery and involve autosaves...those do hang around from previous sessions, if you recall. And they are a sure sign of a crash of some kind.

    I'll also confess that there was one thing I held back previously. I did find a kludge to get a clean shutdown via the command line. The simple, but useful, wmctrl has a "-c" option to shutdown an application. I believe it asks the window manager to do that (using _NET_WM_ACTION_CLOSE?). Somehow that causes a graceful shutdown of RG...no lock file...no complaints from JACK. If it used a signal, knowing which one would be useful? But it's a kludge and not exactly portable.

    Anyway, other than as a resource management exercise, how could this be useful? If a "--play" option were added to the command line, then RG opens, automatically plays the selected rg file to the end of the composition (which can already a preference to stop at the end). And now it seems natural to want to close that session the same way it was started i.e. from the command line, or even remotely, without using the interface. But then the ugly shutdown, lock files...the unknown dangling resources etc....begs for a clean termination signal of some kind.

    With a clean shutdown, you have the makings of a RG playlist of sorts...just a simple list of rg commands in a script will run through all the sessions in turn...so long as no error by one of the sessions kills off the script...and yes it's easy to trap any such error even now with RG as it is...but that's a kludge. In any case to keep possibilities open in the future, it also suggests having a graceful signal shutdown.

    For the playlist angle, an alternative would be the "--play" option mentioned above, along with something like "--exit-after-play" (or shorter). Then RG will obviously shutdown cleanly, because it already knows how to, and then the playlist script moves onto the next session. And during all of this, there's nothing to prevent the user stopping the session via the interface to make any changes etc , saving it and closing it manually, at which point the playlist continues uninterrupted.

    Well...it's a doorway that doesn't seem to require that much up front work.

    I didn't try that SIGUSR1 signal...I'll go do that since for all I know it might do the graceful shutdown.

     
  • musewhirl

    musewhirl - 2025-07-11

    I checked out the SIGUSR1 signal. Visually, it partially works:

    void
    RosegardenMainWindow::signalAction(int fd)
    {
        int message;
    
        if (read(fd, &message, sizeof(message)) == -1) {
            RG_WARNING << "signalAction(): read() failed:" << std::strerror(errno);
            return;
        }
    
        switch (message) {
            case SIGUSR1:
                slotFileSave();
                break;
            default:
                RG_WARNING << "signalAction(): Unexpected signal received:" << message;
                break;
        }
    }
    

    The switch statement traps the signal and executes a save (slotFileSave) which can be seen in the application interface itself immediately as well as the rg file timestamp. However it does not then exit RG like the comment portion says for the following function. RG remains on screen awaiting its fate.

    /* Handler for system signals (SIGUSR1, SIGINT...)
    
     * Write a message to the pipe and leave as soon as possible
     */
    RosegardenMainWindow::handleSignal(int sig)
    

    According to the man page for signal:

    Signal  Standard    Action  Comment
    SIGUSR1 P1990       Term    User-defined signal 1
    SIGUSR2 P1990       Term    User-defined signal 2
    

    So both are TERM-like. SIGUSR1 is caught, but SIGUSR2 escapes and is treated like SIGTERM, along with dead lock files etc.

    The simplest and safest initial implementation might be to use SIGTERM as suggested i.e. slip one into that switch statement and save SIGUSR1 for a rainy day. In other words:

    • If RG has not been edited i.e. there are no changes to save, then just carry out the usual RG exit which is initiated by CTRL-Q, the window x-button or ALT-F as quickly as possible. That would represent a graceful shutdown. Then everything dovetails to normal RG exit. But that exit has to close RG, otherwise this change could be interpreted as new, externally visible, bad behavior warranting a SIGKILL rebuke :-) Perhaps testing with one of the USR signals first would be wise.
    • If there are RG changes to save, then I personally would not automatically "save" like SIGUSR1 anyway, because the user may be in the middle of something they don't want saved. It would be best to do what you (Ted) suggested above i.e. go for an autosave, throw the SIGTERM onward, and hope for the best i.e. crash recovery.

    Well, that's my cent's worth.

     
  • Ted Felix

    Ted Felix - 2025-07-14

    Looks to me like the SIGUSR1 handler was an experiment. I say we do the following:

    1. Make SIGTERM force an auto-save and then exit. Maybe clean up the lock file, but that's not critical.
    2. Open a feature request for a --play feature that will play an .rg file and exit.
     
  • Ted Felix

    Ted Felix - 2025-07-14

    @musewhirl has opened [feature-requests:#532] to satisfy #2 above.

     

    Related

    Feature Requests: #532


Log in to post a comment.

MongoDB Logo MongoDB