Hotboot supporting SegVio?

Posted by Zeno on Sun 10 Apr 2005 05:09 AM — 8 posts, 25,767 views.

USA #0
I want to add SegVio where on a crash, a hotboot will execute. I've seen this on many muds, and here is a snippet for it:
http://ftp.mudmagic.com/diku/merc/smaug/Star_Wars/snippets/ECopyover.txt

But I think everything I've seen is copyover, not hotboot. Is this possible? Could someone explain to me how it would be?
Canada #1
It is possible, as I have this working on my mud currently. The easiest way that I found was to have three functions: do_hotboot, emergency_hotboot, and hotboot. do_hotboot is the same, but segvio call crash_hotboot(), which is basically this:
void crash_hotboot(void)
{

        echo_to_all(AT_RED,
                    "\n\rReality swirls and changes around you, and things are not quite as they were...\n\r",
                    0);
        snprintf(log_buf, MSL, "%s", "Hotboot initiated by crash.");
        log_string(log_buf);
        hotboot(FALSE, TRUE);
}
So the command calls the player checks, safety stuff, etc, where this just writes the files and gets it over with.

Also, dunno if this helps, but this is my segvio code that will crashover and still produce a core
static void SegVio(int signum)
{
        pid_t     p;
        DESCRIPTOR_DATA *d;
        char      buf[MSL];

        signum = 0;
        log_string("SEGMENTATION VIOLATION");
        log_string(lastplayercmd);
        mudstrlcpy(lastplayercmd, "", MIL * 2);

        if (sysdata.PORT)
        {
                signal(SIGPIPE, SIG_DFL);
                signal(SIGSEGV, SIG_DFL);
                signal(SIGTERM, SIG_DFL);
                if ((p = fork()) == 0)
                {
                        abort();    /* Abort child */
                }

                if (access("core", F_OK) == 0)
                {
                        snprintf(buf, MSL, "%d.core", p);
                        rename("core", buf);
                }

                signal(SIGPIPE, SIG_IGN);
                signal(SIGSEGV, SegVio);
                signal(SIGTERM, SigTerm);   /* Catch kill signals */

                if (crashover == TRUE)
                {
                        crashover = FALSE;
                        log_string("Crashover ready. Starting crashover.");
                        crash_hotboot();
                }
                else
                {
                        log_string("Crashover not ready. Shutting down.");
                        abort();
                }

                if (crashover == TRUE)
                {
                        crashover = FALSE;
                        echo_to_all(AT_RED,
                                    "&RATTENTION!! Crash, Hold on while we try and recover.\a",
                                    ECHOTAR_ALL);
                        for (d = first_descriptor; d; d = d->next)
                                flush_buffer(d, TRUE);
                        log_string("Crashover ready. Starting crashover.");
                        crash_hotboot();
                }
                else
                {
                        log_string("Crashover not ready. Shutting down.");
                        abort();
                }

        }
        abort();
}


One thing you want to be careful of is loops. If some of the data in the hotboot is being written and its corrupt, it will crash again, call the function, etc. Thats what the "if (crashover == TRUE)" call are for. Hope this helps.
USA #2
What is your hotboot function? Just do_hotboot or something else? Also, is sysdata.PORT, is that important? I'm trying to be extra safe here so I don't cause more problems than I already have. (password corruption)
Canada #3
The sysdata.PORT thing is just a bool I use to differentiate to my code whether its not coding port or not. You could easily strip that out.

My do_hotboot is quite modified to accept argument for saving or not, for creating the files but not actually performing the execl, and for warning of possible crashes, etc. The actual void hotboot file starts the file declarations and then the save_world call, and goes from there.
USA #4
Ah okay, I already have that made. SigTerm seems to be undeclared. Am I missing it? Is is that part of SWR? Okay to just go ahead and comment out that line with SigTerm?

Also, where is crashover declared? At the top of the file? Like this:
crashover              = TRUE;
Canada #5
Sigterm is in there because I've included the code on samson's site to handle it, you can comment it without issue.

As for crashover, its just at the top of the file like such:
fd_set    exc_set;  /* Set of desc's with errors    */
int       maxdesc;
bool      crashover;    /* Perform Crashover?      */


Then in main I have
#if defined(MALLOC_DEBUG)
        malloc_debug(2);
#endif

        crashover = FALSE;
I also use
void init_crashover(void)
{
        if (!crashover)
        {
                bug("Notice: Crashover system is ready.");
                crashover = TRUE;
        }
}
Then just a simple function in update.c to call init_crashover at the appropriate time, and then your protected. I have mine set to about 45 seconds.
USA #6
I've tried out the basics, and it doesn't seem to work. I used your SegVio (modified to work with my code). This is in game_loop:

void game_loop( )
{
    struct timeval        last_time;
    char cmdline[MAX_INPUT_LENGTH];
    DESCRIPTOR_DATA *d;
/*  time_t      last_check = 0;  */

#ifndef WIN32
    signal( SIGPIPE, SIG_IGN );
    signal( SIGALRM, caught_alarm );
#endif

     signal( SIGSEGV, SegVio );
    /* signal( SIGSEGV, SigCrash ); */
    gettimeofday( &last_time, NULL );
    current_time = (time_t) last_time.tv_sec;


My hotboot function as stripped of the fighting checks etc. Does anything look wrong so far?

I get this in the logs:

194 Sat Apr  9 23:32:49 2005 :: SEGMENTATION VIOLATION
195 Sat Apr  9 23:32:49 2005 :: Zeno used crash
196 Sat Apr  9 23:32:49 2005 :: Crashover not ready. Shutting down.


[EDIT] Oh nevermind, I need to add that update function. How would I add it at a certain interval?

Also, the crash restore only seems to work once. I'd make it crash, it'd hotboot restore. And a few minutes later:
Log: [*****] BUG: Notice: Crashover system is ready.

But when I make it crash again, it just crashes, no hotboot restore. The logs indicate nothing of SegVio:

562 Sun Apr 10 10:43:13 2005 :: Hotboot recovery complete.
563 Sun Apr 10 10:43:17 2005 :: [*****] BUG: Notice: Crashover system is ready.

And that's the end of the log. Which means the crash happened after that.
Amended on Sun 10 Apr 2005 05:45 PM by Zeno
Canada #7
If there is a time that an update already uses, it would be easiest to just throw the call to the update in there. If not, you need to define a new pulse type in mud.h, and basically copy a pre-existing pulse and modify it to your time intervals.

As for segvio not being called after it has already crashed, I can only suggest that you ensure that you still have "signal(SIGSEGV, SegVio);" in the segvio function.