Catching memory crashes

Questions and Answers about all things *OS (macOS, iOS, tvOS, watchOS)

Catching memory crashes

Postby cahoots » Fri Oct 26, 2018 4:01 pm

Hi, I'm trying to find a good way to catch memory crashes, and the best way I know of (https://code.fb.com/ios/reducing-fooms- ... k-ios-app/) doesn't really do the job. For other crashes, it's easy enough to catch it with signal handlers, but with memory crashes we don't get a signal we can intercept. Is there some crazy way to determine if the app's last session terminated due to a memory crash? I'm most interested in this for iOS, but anything would help.
cahoots
 
Posts: 10
Joined: Mon Oct 08, 2018 3:56 pm

Re: Catching memory crashes

Postby morpheus » Sun Oct 28, 2018 8:36 pm

You actually DO get a signal you can intercept. As explained in detail in Chapter 9. The FB approach in the article isn't the right way to do it, and the article is quite inaccurate . TL;DR: There is more than one way to react to memory pressure, before you get SIGKILLed by jetsam. Rather than explain here, just read the relevant pages:

283.png
283.png (587.85 KiB) Viewed 1165 times


284.png
284.png (557.45 KiB) Viewed 1165 times


285.png
285.png (586.88 KiB) Viewed 1165 times



And mental note to myself: iOS 12 now has /usr/libexec/ReportMemoryException.
morpheus
Site Admin
 
Posts: 716
Joined: Thu Apr 11, 2013 6:24 pm

Re: Catching memory crashes

Postby cahoots » Mon Oct 29, 2018 9:23 pm

Thanks, that makes sense. However, when I try it, kevent returns immediately, adds EV_ERROR to the flags for eventEv, and sets ENOTSUP for the data for eventEv. FYI I'm using an iPhone 8 with iOS 12.0 (16A366). Code:
Code: Select all
    struct kevent changeEv = {0};
    changeEv.filter = EVFILT_VM;
    changeEv.flags = EV_ADD | EV_ENABLE;
    changeEv.fflags = NOTE_VM_PRESSURE_SUDDEN_TERMINATE;
    struct kevent eventEv = {0};
    int n = kevent(kq, &changeEv, 1, &eventEv, 1, NULL);
    assert(n > 0 && !(eventEv.flags & EV_ERROR));
    close(kq);
cahoots
 
Posts: 10
Joined: Mon Oct 08, 2018 3:56 pm

Re: Catching memory crashes

Postby morpheus » Tue Oct 30, 2018 11:19 pm

you're using it wrong; There's an example on how to do the kevent loop in the 1st ed. First set, then read. Also look at XNU's side of things (somewhere in bsd/kern - not near the source right now so can't tell)
morpheus
Site Admin
 
Posts: 716
Joined: Thu Apr 11, 2013 6:24 pm

Re: Catching memory crashes

Postby cahoots » Wed Oct 31, 2018 11:06 pm

Ok, I've tried the example from the first book after replacing the pid with 0, EVFILT_PROC with EVFILT_VM, and NOTE_EXIT | NOTE_FORK | NOTE_EXEC with NOTE_VM_PRESSURE_SUDDEN_TERMINATE. Unfortunately, it still doesn't work, giving ENOTSUP when I run it. Any ideas?

Code: Select all
int main (int argc, char **argv)
{
    pid_t pid; // PID to monitor
    int kq; // The kqueue file descriptor
    int rc; // collecting return values
    int done;
    struct kevent ke;
    pid = atoi(argv[1]);
    kq = kqueue();
    if (kq == -1) { perror("kqueue"); exit(2); }
    // Set process fork/exec notifications
    EV_SET(&ke, 0, EVFILT_VM, EV_ADD,
           NOTE_VM_PRESSURE_SUDDEN_TERMINATE, 0, NULL);
    // Register event
    rc = kevent(kq, &ke, 1, NULL, 0, NULL);
    if (rc < 0) { perror ("kevent"); exit (3); }
    done = 0;
    while (!done) {
        memset(&ke, '\0', sizeof(struct kevent));
        // This blocks until an event matching the filter occurs
        rc = kevent(kq, NULL, 0, &ke, 1, NULL);
        if (rc < 0) { perror ("kevent"); exit (4); }
    } // end while

    NSLog(@"fail");

    return 0;
}
cahoots
 
Posts: 10
Joined: Mon Oct 08, 2018 3:56 pm

Re: Catching memory crashes

Postby cahoots » Tue Nov 06, 2018 11:23 pm

This would be a huge win for iOS developers if it actually works
cahoots
 
Posts: 10
Joined: Mon Oct 08, 2018 3:56 pm

Re: Catching memory crashes

Postby septium » Sat Nov 17, 2018 10:26 pm

High-level way of doing it:

On the jailbroken iDevice you can hook into [SBMainWorkspace processDidExit:] call in SpringBoard to monitor terminations and query for details.

Code: Select all
void _hooked_SBMainWorkspace_processDidExit_impl(id self, SEL cmd, id process) {
    _orig_SBMainWorkspace_processDidExit_impl(self, cmd, process);
    if ([process isKindOfClass:objc_getClass("FBApplicationProcess")]) { //theoretically it can be FBProcess, without exitContext
        NSString *bundleID = [process bundleIdentifier];
        FBApplicationProcessExitContext *exitContext = [process exitContext];
        //look for details
        //[exitContext consideredJetsam]; //YES on OOM crash
        //[exitContext fairPlayFailure];
        //[exitContext terminationSignal];
        //[exitContext exitCode];
    }
}


Don't forget to include relevant private headers, or just declare methods in private category of NSObject.

http://developer.limneos.net/?ios=11.1.2&framework=SpringBoard&header=SBMainWorkspace.h
http://developer.limneos.net/?ios=11.1.2&framework=FrontBoard.framework&header=FBApplicationProcess.h
http://developer.limneos.net/?ios=11.1.2&framework=FrontBoard.framework&header=FBApplicationProcessExitContext.h
septium
 
Posts: 39
Joined: Thu May 04, 2017 10:04 am

Re: Catching memory crashes

Postby cahoots » Sun Nov 18, 2018 8:20 pm

septium, thanks for the advice. My goal here is to find a way to do this for non-jailbroken devices, ideally without private API usage but ok if necessary.
cahoots
 
Posts: 10
Joined: Mon Oct 08, 2018 3:56 pm

Re: Catching memory crashes

Postby septium » Mon Nov 19, 2018 9:22 am

So you want to say that kevent on EVFILT_VM/NOTE_VM_PRESSURE_SUDDEN_TERMINATE will work from non-entitled sandboxed process? This would be a huge luck and huge miss from Apple if the answer is yes.
septium
 
Posts: 39
Joined: Thu May 04, 2017 10:04 am

Re: Catching memory crashes

Postby LowellSti » Mon Nov 19, 2018 3:01 pm

Why do you say that, Septium? You think it's not meant to work like that?
LowellSti
 
Posts: 1
Joined: Sat Oct 06, 2018 9:14 am

Next

Return to Questions and Answers

Who is online

Users browsing this forum: No registered users and 2 guests