[tips] VSH plugin module termination - how to do it cleanly

Discuss the development of new homebrew software, tools and libraries.

Moderators: cheriff, TyRaNiD

Post Reply
Fanjita
Posts: 217
Joined: Wed Sep 28, 2005 9:31 am

[tips] VSH plugin module termination - how to do it cleanly

Post by Fanjita »

I just spent a couple of weeks poking away at a frustrating crash, apparently during module_load of the piKey PRX in game mode.

I finally managed to nail it, and learnt a few things along the way. Seems these things aren't new, but aren't widely publicised, so it seemed worth making a post to save other people's time.

The root cause was that the reboot from VSH to GAME is not very good at properly tidying everything up automatically. I had a kernel thread that just wasn't getting stopped, and presumably it was crashing at some point during the invocation of reboot.bin by the kernel.

Because of that, what I thought was a crash during the load of the module during GAME boot, was actually a crash of the VSH module during VSH shutdown. So I saw lots of odd things that were seemingly inexplicable.

The main odd thing:

SYMPTOM: Adding sceKernelDelayThread() in random places stopped the module from crashing "during startup".
EXPLANATION: sceDisplayWaitVBlank() doesn't yield the thread in the same way as sceKernelDelayThread(). It seems that module tidyup during reboot can't kill kernel threads that only yield via waitvblank. So, a kmode main loop that was basically:

Code: Select all

while(1)
{
   sceDisplayWaitVBlank();
   ...
}
would cause a crash during reboot, but a loop like this:

Code: Select all

while(1)
{
   sceKernelDelayThread(100);
   sceDisplayWaitVBlank();
   ...
}
was fine.

An alternative solution I found before I understood the yield behaviour:

There are some little-known module callbacks that you can use to detect reboot, and cause your module to exit. It seems that module_stop() is not called for OE VSH plugins, so that's no help. But these functions:

module_reboot_phase
module_reboot_before

are. I haven't looked into any more detail on module_reboot_phase(), but noticed that it is called 3 times during the boot to GAME mode.

module_reboot_before() seems to be called last thing before the crash I was seeing, so I added some code to do the following, which will also avoid the crash:

Code: Select all

int module_reboot_before()
{
  terminate_flag = 1;
  sceKernelWaitThreadEnd(mainthreadid, 0);
  return 0;
}
(assuming that the while(1) in the main loop is replaced with while(!terminate_flag), in the obvious way).

I have no idea of the true function prototypes for these funcs, but for my purposes int func(void) was sufficient. If you want to use them, you need to add them to your exports.exp, alongside module_start.

There's also another standard prx function, module_bootstart, but I haven't seen that called at any point in my module - presumably it happens after the reboot.

References I used to find some of this info:
1. http://hitmen.c02.at/files/yapspd/psp_doc/chap26.html
Groepaz's great doc, search for module_start.

2. http://svn.pspsp.org/svn/CheatMaster/crt0_prx.c
Although I don't think the prototype for _reboot_before is likely to be correct either.


Hope this helps someone to avoid the pain I've gone through recently. :)
Got a v2.0-v2.80 firmware PSP? Download the eLoader here to run homebrew on it!
The PSP Homebrew Database needs you!
califrag
Posts: 30
Joined: Wed Apr 04, 2007 4:43 pm

Post by califrag »

hi Fanjita,
I've been developing a prx module to replace my "lftv" icon in the xmb.

The functions module_reboot_phase and module_reboot_before provide clean termination going into "GAME" mode, only, correct? So basically this just stops the module before going into a game by changing your termination flag.

I want to make sure first that I understand what these functions are for.

I am also curious if these functions allow for clean termination within the VSH so the prx can be "loaded" again.

What I am trying to do is replace lftv_plugin.prx with my own. After starting up my psp, module is not loaded at this point. I launch the module from lftv menu icon, module loads and runs.
When the exit button-combo is pressed, the module stops, and unloads. Now if I want to launch my module again (without rebooting, or entering a game and exiting) from the lftv icon, it does not work. I am assuming because something is still loaded into memory preventing it from launching or loading again.

Do you know how to fix this issue? Is it have anything to do with the module_reboot functions? I appreciate any ideas you can contribute as I have been pretty frustrated trying to figure it out. Thanks Fanjita!

-eternal 'jita fan
Post Reply