2

The documentation for the Windows Debugger API mentions a debug event called RIP_EVENT. It offers little explanation of what a RIP_EVENT is, only stating that the structure "contains the error that caused the RIP debug event." In my own debugger, I have never encountered this event, so I am uncertain how to handle it.

There are precious little resources online explaining what the event is. This blog is as confused as I am:

I find very few documents about this event, only mentioned with words like system error or internal error. So I decide to print a error message and skip it. As my project is not fully tested, I have never encountered such a situation.

The Writing A Debugger CodeProject claims the event "occurs if your process being debugged dies unexpectedly." Similarly, this OALabs video states that the RIP_EVENT occurs if the process doesn't exit gracefully.

This seems to be the general consensus amongst the few resources I can find. The problem is, of all the ways I can conceive of to kill a process in unexpected fashion, none of them trigger a RIP_EVENT. Last Chance Exceptions trigger a DEBUG_EVENT, eventually followed by an EXIT_PROCESS_DEBUG_EVENT, instead. If anything, I would expect that terminating the process in Task Manager wouldn't be considered a "graceful exit," but it too triggers an EXIT_PROCESS_DEBUG_EVENT, not a RIP_EVENT. This makes me wonder if the event is even associated with process termination at all, or if that's just a confident assumption based on the name "RIP."

I'm left to speculate why I've never seen this event before and in what scenario it could potentially arise:

  • Assuming a RIP_EVENT does occur when the process dies somehow, does the RIP_EVENT replace the EXIT_PROCESS_DEBUG_EVENT, or can I expect to receive both events?
  • How do popular debuggers like Visual Studio or WinDbg handle the RIP_EVENT? What is the correct way to handle one? Do I even need to do anything if I receive one?
  • Does the "RIP" in RIP_EVENT refer to the instruction pointer in x64? Would that imply it is exclusive to x64 and never occurs for x86? Or perhaps it is for some other CPU architecture I don't care about?
  • Does it occur when connection is lost while debugging a remote process? This is another scenario I thought might cause it, but it'd be difficult for me to test.

Update: I began digging even further into this, because I wasn't satisfied with the guesses so far, and found something interesting. There is an export of USER32 called SetDebugErrorLevel. There is no official documentation for it that I can find, but if this source is to be believed, it would make a lot of sense.

The SetDebugErrorLevel function sets the minimum error level at which Windows will generate debugging events and pass them to a debugger.

Parameters

dwLevel Specifies the minimum error level for debugging events. If an error is equal to or above this level, Windows generates a debugging event. This parameter must be one of the following values:

Value: 0

Meaning: Does not report any errors. This value is the default error level.

Value: SLE_ERROR

Meaning: Reports only ERROR level debugging events.

Value: SLE_MINORERROR

Meaning: Reports only MINORERROR level and ERROR level debugging events.

Value: SLE_WARNING

Meaning: Reports WARNING level, MINORERROR level, and ERROR level debugging events.

Particularly because the RIP_INFO structure contains a dwType field with these same values, I think it is likely that RIP_EVENT was intended to be thrown as a part of this mechanism. The thing is, SetDebugErrorLevel - although it exists in USER32 - does nothing. Looking at the disassembly reveals it simply returns immediately. Furthermore, these types were clearly intended to be specified in calls to SetLastErrorEx, though it too goes unused, as the documentation explains:

Currently, this function is identical to the SetLastError function. The second parameter is ignored.

...with the second, unused parameter being dwType, which was probably meant to take in the SLE_ERROR, SLE_MINORERROR, and SLE_WARNING types (with "SLE" standing for SetLastError.) From this, I infer that RIP_EVENT was probably intended to be thrown whenever SetLastErrorEx was used to set a new error level, but this feature has been abandoned. This is my best theory, but it is still only a guess, as the documentation never goes so far as to explicitly state this.

1 Answer 1

1

AFAIK you're not supposed to handle it and I doubt you reasonably could. The sources you cite are right about what RIP means in this context.

This event occurs in response to a DBG_RIPEXCEPTION (== ((NTSTATUS)0x40010007L); see ntstatus.h). The message for this status code is "Debugger received RIP exception." (not helpful ;)) and a corresponding Win32 error code exists by the name ERROR_DBG_RIPEXCEPTION (== 695L; see winerror.h, same message text).

Arguably you could synthesize this event by calling RaiseException with the DBG_RIPEXCEPTION code. You could then play with passing different arguments and filling the data and seeing what carries over into the debugger.

I, too, am not aware of anything that raises that specific code, but be it cosmic rays or anything else, it seems to signal the sudden and unexpected "death" of a process out of the ordinary.


Assuming a RIP_EVENT does occur when the process dies somehow, does the RIP_EVENT replace the EXIT_PROCESS_DEBUG_EVENT, or can I expect to receive both events?

From what I gather, you can expect both. They signify different circumstances, however. RIP_EVENT seems to be purely about the sudden and unexpected "death" of a process, not other ways of the process exiting (and the OS getting to clean up after it). One guess would be that this could get synthesized on the client in remote debugging scenarios.

How do popular debuggers like Visual Studio or WinDbg handle the RIP_EVENT?

I think they don't. That event is supposed to be the exception to the exception, so to speak.

What is the correct way to handle one? Do I even need to do anything if I receive one?

As noted above, I think you're not supposed to care about it. At most log it (to notify the user).

Does the "RIP" in RIP_EVENT refer to the instruction pointer in x64? Would that imply it is exclusive to x64 and never occurs for x86? Or perhaps it is for some other CPU architecture I don't care about?

Nope it's not about the instruction pointer in x64. It predates x64.

Does it occur when connection is lost while debugging a remote process? This is another scenario I thought might cause it, but it'd be difficult for me to test.

Seems like we came to the same conclusion with this one.

However, I'd like to offer another option: RIP_EVENT could be a remnant and no longer applicable to modern Windows. NT has a long history and it could well be something that was dropped along the way ... for all we know it could originate from something that relates to OS/2 and Microsoft's/IBM's collaboration before they parted ways. This is just a guess, too. But it would explain the absence of information. It could also be something that was introduced from the Win32s lineage (Windows 9x/Me) and subsequently dropped. Remember that NT 4.0 took up the desktop look&feel from Windows 95 at the time.

Unless you're working for Microsoft and have access to internal documentation, source code history and some of the original developers, I don't think you'll get much more info than what you found already.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.