Exit codes

An Azure Sphere high-level application can use exit codes to return information related to where in the code the error occurred and why it occurred. An exit code corresponds to a value between 0 and 255, where 0 indicates success.

Define and use exit codes in an app

Follow these guidelines to define and use exit codes in an app:

  • Create an exit code variable and initialize it to success (0) at the start of the application.
  • Return an exit code from any function where an error has caused the application to exit. The function exit codes can provide detailed information about operational errors. For example, a function that sends a message to an IoT Central application might return an error code that provides details about where failure occurred: in message construction, IoT connection, message transmission, and so forth. A different function responsible for initializing peripherals would return a unique exit code to indicate a failure with a specific peripheral.
  • If a failure exit code (nonzero) is set or returned by a function, ensure it is immediately propagated back for the main function to return. This will cause the application to exit with the given exit code. The Azure Sphere OS will immediately restart your application (unless you were using the debugger with a connected development board), and you can use error reports to diagnose the reason an exit ocurred.

Error reports

When a high-level application exits, the Azure Sphere OS logs the exit code returned by your application, and later uploads an error report containing this information to the Azure Sphere Security Service daily. By comparing the exit code in the error report against the exit codes defined in your application, you can often determine the location and cause of the error. See Interpret AppExits for more information.

RTApps cannot return error data directly to the Azure Sphere Security Service. If you want to implement error tracking in an RTApp, you'll need to communicate the error data from the RTApp to a high-level app using the inter-core communications mechanism. See Communicate with a high-level application and Communicate with a real-time capable application for details.

Sample exit code implementation

The following snippets show a sample of how you can incorporate exit codes into a high-level application.

First, declare an ExitCode enum in your application that you can use to define all of your specific exit code values. Then, initialize a global exitCode variable to the success state (0).

// Exit codes for this application.
typedef enum {
ExitCode_Success = 0;
ExitCode_Init_LED = 1;
ExitCode_Init_Button = 2;
} ExitCode;

// Initialize the termination state.
static volatile sig_atomic_t exitCode = ExitCode_Success;

Functions that contain error cases that should terminate the application should return an ExitCode enum. If an error case is reached that should terminate the application, return the specific exit code you defined for that case. In the below example, the InitPeripheralsAndHandlers function is defined, which initializes an LED and a button. If either initialization fails, the corresponding ExitCode value defined above is returned.

// Initialize the peripherals and handlers. Return ExitCode_Success if all resources were allocated
// successfully; otherwise another ExitCode value which indicates a specific failure.
static ExitCode InitPeripheralsAndHandler(void)
{
	// Open SAMPLE_LED as output.
	led = GPIO_OpenAsOutput(SAMPLE_LED);
	if (led == -1) {
		return ExitCode_Init_LED;
	}

	// Open SAMPLE_BUTTON as input.
	button = GPIO_OpenAsInput(SAMPLE_BUTTON);
	if (button == -1) {
		return ExitCode_Init_Button;
	}
	return ExitCode_Success;
}

After initialization, the application stays in the main loop as long as the global exitCode variable is still assigned the initial success value. If any part of the main application logic ever sets the exitCode variable to a value other than success, the application will break out of the main loop and exit with the set exitCode. The Azure Sphere OS will capture the app exit event and corresponding exit code in an error report, then restart your application.

int main(int argc, char* argv[])
{
	exitCode = InitPeripheralsAndHandler();

	while (exitCode == ExitCode_Success) {
		// Run other application functions within this loop.
		// When a function encounters an error, set a corresponding exit code and return from that function.
		// This will break out of the while loop if the exit code is not ExitCode_Success.
	}

	return exitCode;
}