How About Using Setunhandledexceptionfilter()

So my core randomly crashed. When I restarted I realized that certain progress was lost:

All these were reset to the point when I originally loade my character, 10 minutes prior to the crash

  • My pet’s level was reset

  • My enchanting skill was reset, I lost 10 points from the DE I had done

  • My location was reset, I was put back into the zone I was in when I originally loaded

  • My reputation was reset, I lost the reputation from quests I’d done

Since quests themselves were not reset, they were listed as completed, the lost reputation was actually lost since I couldn’t redo the quests again.

So I got to thinking, I’ve implemented SetUnhandledExceptionFilter() in VB6 a long time ago to either prevent programs from GPF or at least perform cleanups before exiting after a GPF.

Could we implement this in TC so in the event of a crash we could save things such as character progress before exiting the core?

I’ve always been taught (and practiced) to try and avoid fault handling. Log it, sure, so you can figure it out later, but If something is bad enough to coredump / segment fault your program then attempting to salvage data to write to storage is gambling with your data integrity. How can you verify your character is un-corrupted in memory if part of the address for it was overwritten during the segfault? Then you’re just writing a corrupt character to your DB and making life worse the next time you go to load it and suddenly it doesn’t work / works incorrectly.

You could write the character data to an SQL dump similar to the console command. That way the server operator could review the data and decide if they want to import it into the character db.

Consider the lost reputation issue. The quests are marked completed so they can’t be redone but the approx. 1200 rep from them is lost forever.

It could at least allow the core to exit gracefully rather than the hard crash it does now.

Wouldn’t it be easier to decrease the delay saving stuff? I’m sure on larger servers you don’t want writes happening prior to logging off too often for performance reasons but on a small server you can save data more frequently with no ill effects.

Also, isn’t there a GM command to hand out free rep? That might be easier than reviewing data files from a crash.

I was actually thinking of a similar way to write to 2 tables similar to a ‘characters2’ that mocks ‘characters’, but during a timed sequence. An example would be every 10 minutes the ‘characters_backup’ would update just for that character (saving performance). That way you have a cushion window during a crash, before the crash you would have “less” data lost, and updates to just that 1 character when the character table was updated.

Not sure how it would affect performance over all and also not sure if it would be healthy to import characters_backup to characters after recovering from a crash.

Actually I dusted off my old VB implementation from 2005 and it appears that somewhere in an update to XP and Vista, Microsoft decided to break the functionality of SetUnhandledExceptionFilter().

My DLL which I used in many applications now doesn’t return from the handler function after catching an exception. It just hangs the application. I read some articles that somewhere with VS8 there was an update to the runtimes that changed how this function worked.

Damnit, Microsoft. Always breaking stuff.

Like I said, logging info is usually ok. So I wouldn’t see an issue of trying to get a raw data dump to be later reviewed / used if there was merit to it.

The lost rep is mitigated in the same manner the data dump you propose – hand reviewed and updated as needed. Personally I believe that for the size of data stored on characters you eventually reach a tipping point where it becomes easier to deal with things on a case-by-case basis and reimburse/fix them as needed; as opposed to attempting to diff/deal with a dump of all active characters. Rep is just a number in a DB column. I think (haven’t looked myself) there may even be console/in-game GM commands to modify it; so no huge hassle there.

As far as a graceful exit…Once the program has faulted so severely to crash all bets are off. It’s difficult to determine is the crash was out of bounds memory, a hardware memory fault, or any other number of things – and then cope with it accordingly. Even implementing a fault handler, what does it help if you write to the wrong memory address which ends up bleeding into the memory space where your fault handler is loaded? After a crash all behavior is pretty undefined and IMHO should be treated as untrusted to the level of a rooted PC: that is, give up and start clean (let it crash, start it fresh).

Isn’t this what the .save and .saveall commands are for? You can decrease the auto-save timer in the config as well.

Well the problem with reducing the save timer is you inevitably cause lag if you set it too low.

I guess I was just trying to brainstorm how to minimize loss of data in the event of a crash. In my case I don’t even know what caused the crash. I’d been playing for about 20 minutes and the core itself had been up for 3 days. I was just running down the road in Elwynn and I turned the camera to look at a bear and the core just died.

decreasing save timer is not an option on very high loads servers. you could however add a piece of code that would trigger full character save when receiving reward from a quest. it would solve the problem wouldn’t it ?

as someone gets rewarded from 10 quests within a minute happening over 500 characters?

Hmmm, you could filter which data is saved (only save data that the quest actually modified), delay saving by X secs (in case they would get rewarded for lots of quests in short time) and make sure the sql queries are non blocking (i do not know how trinity handles databases exactly, so that last part might be impossible).

It may be somewhat tricky but if the circumstances make you need less data loss in crash, this might be useful to have at hand.

Feel free to discuss, i’m not taking offense /emoticons/default_smile.png

Well, i don’t think 500 ppl will have 10 quest rewarded at once.

Yes but Kendra is right in her logic, taking in account worst case scenario is best way to write failsafe code.

Btw, what the op is actually talking about has actually been implemented in mangosr2, rsa’s mangos fork. Porting it over trinity is being discussed HERE.

How faster is it looping through, let’s say, 10000+ members dynamic list than doing the same in a DB table?