Shutting Down Your Application

There are 3 different ways the user can trigger quitting an application.

Pressing the POWER Button immediately after an application starts running does not result in an exit message. The POWER Button is enabled only after the MCP_PowerButtonControl(1) returned 0 message is displayed.

The Wii U system software makes all these paths appear the same to the application so that the application can perform identical exit processing.

If currently in foreground mode, to skip the transition to background (BG) mode before exiting, use OSEnableForegroundExit for applications that can tolerate multiple exit paths.

Shutdown Considerations for Multiple Cores

If the game has inflight file system (FS) and network (NET) APIs running on cores 0 and 1 or if the user triggers a game shutdown, the game shutdown sequence must provide the following correct sequence of events:

  1. The game receives processing cycles on cores 0 and 1.
  2. The inflight APIs complete and issue any necessary callbacks in order.
  3. The game receives the shutdown event.

Shutdown Sequence

The basic process for shutdown:

  1. Transition to Background Mode.

    This is the same process as switching user interface to HBM via an OS_SYSTEM_MESSAGE_DATA0_RELEASE_FOREGROUND message from the System Message Queue. The application releases all of the User Interface Devices when switching to BG mode. The system automatically triggers a transition to BG mode if it is required for shutdown. If process exit is requested at HBM, the application is already in BG mode.

  2. Cafe Core OS (COS) issues a process exit message to the application.

    The application must wait for the OS_SYSTEM_MESSAGE_DATA0_EXIT message from the System Message Queue prior to proceeding with exit processing. The COS provides CPU cycles for all 3 cores during exit processing.

  3. Application must stop all network and close all sockets.
  4. Application should pause or remove threads to allow the CPUs to go idle.

    Ideally, the application can pause/close all threads except the thread performing exit processing. This prevents possible state collision between threads and exit processing. Although it is not absolutely necessary to pause/close all threads, the system exit handler waits for all CPUs to go idle before shutting down drivers. Threads that do not yield may cause the system shutdown to stall. If there are many threads left running during exit processing, there are increased chances for state collision.

    An example of a collision is C++ static global objects. If threads are left running using these objects, calling the exit function will trigger C++ static global destructors and likely cause the program to crash.

    Alarms are considered temporal threads. Applications should attempt to cancel all alarms.

    There is an exception to this step where a thread that calls FS functions synchronously must NOT pause or suspend threads. Synchronous FS functions may block indefinitely if the volume state is changed by a user operation, such as a disc eject, or by a fatal error caused by a programming error. An application must be able to shutdown without waiting for blocked FS function returns.
  5. Call exit API

    There are three ways that you may exit your application:

    • Return from the main function.
    • Call the exit function.
    • Call the _Exit function.

    Returning from the main and calling exit call the destructors of C++ static objects. The order in which the destructors of static objects are called is undefined. If you are not careful with your implementation, objects with inter-dependencies may hang.

    It is difficult to resolve this issue cleanly if you code the exit processing for your application late in the development cycle. In this case, you may use the _Exit function to exit the application without calling the destructors of C++ static objects.

  6. After exit or _Exit are called, any thread left running by the application must NOT:
    • Make any calls to drivers such as Net or FS.
    • Allow any threads to deadlock.
    • Allow any threads to crash.

To make it easier to develop application shutdowns, the 2 exit functions may be called from any core and from inside RPX or RPL.

Shutting Down Process State Diagram

The diagram below shows the process states for a simple shutdown:

  1. This is when main is called
  2. RELEASE_FOREGROUND is retrieved from the system message queue
  3. OSReleaseForeground is called from all three cores
  4. ACQUIRED_FOREGROUND is retrieved from the system message queue
  5. EXIT is retrieved from the system message queue
  6. Game does not do anything. It is already in the foreground in (5)

When exiting from the background, all three cores are scheduled in a round-robin fashion. This is the only case where a game can get CPU time on Core 0/1 in the background.
If it takes a long time to close files (for example, flushing a large writable file), a more complex shutdown sequence may be necessary to allow the application to use UI devices to perform animation while closing files. For an example of this, see the Application Process State Diagram which details a more complex shutdown procedure.

Revision History

2015/03/19 Formatted as 'IMPORTANT' note.
2014/07/17 Remove step 3 (stop or cancel all I/O and close all files); no longer necessary. Add warning to step 4 about synchronous FS calls.
2013/05/08 Automated cleanup pass.