// File: establishment[P]sandman/src/lib.hpp
// Function: ProcessKeeper::startKeeper()
RunStats startKeeper() {
        /// start clock even thou it is already started by the constructor
        wallClock.start();

        /// switch error pipes fd to read errors from the child process in which the
        /// process runs
        close(errorPipes[1]);

        mockSignals();

        /// if checkIntervalMs is not null, status check is on
        if (config.checkIntervalMs) {
            startStatusCheck(config.checkIntervalMs);
        }

        while (1) {
            struct rusage processUsage;
            int processStatus;

            pid_t p;
            p = wait4(processPid, &processStatus, 0, &processUsage);

            /// check if the process was killed by the signal
            if (processStats.processWasKilled) {
                return processStats;
            }

            /// check if wait4 is working properly
            if (p < 0) {
                if (errno == EINTR) {
                    continue;
                }
                Die("wait4: %m");
            }

            /// sanity check
            if (p != processPid) {
                Die("wait4: unknown pid %d exited!", p);
            }

            clearTimer();

            /// Check error pipe if there is an internal error passed from inside the box
            char interr[Base::kDieBufferSize];
            int n = read(errorPipes[0], interr, sizeof(interr) - 1);
            if (n > 0) {
                interr[n] = 0;
                Die("childErrors", interr, true);
            }

            updateStats();
            processStats.update(processUsage);
            Msg("ProcessStatus:%d\n", processStatus);

            if (WIFEXITED(processStatus)) {
                /// the process exited normaly.
                if (WEXITSTATUS(processStatus)) {
                    processStats.resultCode = RunStats::NON_ZERO_EXIT_STATUS;
                    processStats.exitCode = WEXITSTATUS(processStatus);
                } else {
                    processStats.resultCode = RunStats::OK;
                    processStats.exitCode = 0;
                }
            } else if (WIFSIGNALED(processStatus)) {
                processStats.resultCode = RunStats::RUNTIME_ERROR;
                processStats.terminalSignal = WTERMSIG(processStatus);
            } else if (WIFSTOPPED(processStatus)) {
                processStats.resultCode = RunStats::ABNORMAL_TERMINATION;
                Die("Process has stopped. Won't try to start it again.");
            } else {
                processStats.resultCode = RunStats::INTERNAL_ERROR;
                Die("wait4: unknown status %x, giving up!", processStatus);
            }

            if (checkLimits() != RunStats::OK) {
                processStats.resultCode = checkLimits();
            }

            return processStats;
        }
    }

// Assembly:
subq $0x20c8, %rsp           # imm = 0x20C8
movq %rdi, (%rsp)
movq %rdi, %rax
movq %rax, 0x8(%rsp)
movq %rdi, 0x20c0(%rsp)
movq %rsi, 0x20b8(%rsp)
movq 0x20b8(%rsp), %rdi
movq %rdi, 0x10(%rsp)
addq $0x178, %rdi            # imm = 0x178
callq 0xa8740
movq 0x10(%rsp), %rax
movl 0x170(%rax), %edi
callq 0x8cb80
movq 0x10(%rsp), %rdi
callq 0xc93e0
movq 0x10(%rsp), %rax
cmpq $0x0, 0x48(%rax)
je 0xc9050
movq 0x10(%rsp), %rdi
movq 0x48(%rdi), %rsi
callq 0xabd30
jmp 0xc9052
movq 0x10(%rsp), %rax
movl 0x168(%rax), %edi
leaq 0x2024(%rsp), %rsi
xorl %edx, %edx
leaq 0x2028(%rsp), %rcx
callq 0x8c2e0
movl %eax, %ecx
movq 0x10(%rsp), %rax
movl %ecx, 0x2020(%rsp)
testb $0x1, 0x1f8(%rax)
je 0xc90a5
movq (%rsp), %rdi
movq 0x10(%rsp), %rsi
addq $0x198, %rsi            # imm = 0x198
callq 0xc9500
jmp 0xc92a8
cmpl $0x0, 0x2020(%rsp)
jge 0xc90c9
callq 0x8c070
cmpl $0x4, (%rax)
jne 0xc90bb
jmp 0xc9052
leaq 0x2d92d(%rip), %rdi     # 0xf69ef
movb $0x0, %al
callq 0x94bf0
movq 0x10(%rsp), %rcx
movl 0x2020(%rsp), %eax
cmpl 0x168(%rcx), %eax
je 0xc90f2
movl 0x2020(%rsp), %esi
leaq 0x2d90e(%rip), %rdi     # 0xf69f9
movb $0x0, %al
callq 0x94bf0
movq 0x10(%rsp), %rdi
callq 0xabca0
movq 0x10(%rsp), %rax
movl 0x16c(%rax), %edi
leaq 0x20(%rsp), %rsi
movl $0x1fff, %edx           # imm = 0x1FFF
callq 0x8c890
movl %eax, 0x1c(%rsp)
cmpl $0x0, 0x1c(%rsp)
jle 0xc9141
movslq 0x1c(%rsp), %rax
movb $0x0, 0x20(%rsp,%rax)
leaq 0x20(%rsp), %rsi
leaq 0x2d8e0(%rip), %rdi     # 0xf6a17
movl $0x1, %edx
callq 0x94580
movq 0x10(%rsp), %rdi
callq 0xabcc0
movq 0x10(%rsp), %rdi
addq $0x198, %rdi            # imm = 0x198
leaq 0x2028(%rsp), %rsi
callq 0x94150
movl 0x2024(%rsp), %esi
leaq 0x2d8b1(%rip), %rdi     # 0xf6a23
movb $0x0, %al
callq 0x94e30
movl 0x2024(%rsp), %eax
andl $0x7f, %eax
cmpl $0x0, %eax
jne 0xc91e1
movl 0x2024(%rsp), %eax
andl $0xff00, %eax           # imm = 0xFF00
sarl $0x8, %eax
cmpl $0x0, %eax
je 0xc91c3
movq 0x10(%rsp), %rax
movl $0x7, 0x1fc(%rax)
movl 0x2024(%rsp), %ecx
andl $0xff00, %ecx           # imm = 0xFF00
sarl $0x8, %ecx
movl %ecx, 0x1f4(%rax)
jmp 0xc91dc
movq 0x10(%rsp), %rax
movl $0x1, 0x1fc(%rax)
movl $0x0, 0x1f4(%rax)
jmp 0xc926d
movl 0x2024(%rsp), %eax
andl $0x7f, %eax
addl $0x1, %eax
movsbl %al, %eax
sarl %eax
cmpl $0x0, %eax
jle 0xc9219
movq 0x10(%rsp), %rax
movl $0x8, 0x1fc(%rax)
movl 0x2024(%rsp), %ecx
andl $0x7f, %ecx
movl %ecx, 0x1f0(%rax)
jmp 0xc926b
movl 0x2024(%rsp), %eax
andl $0xff, %eax
cmpl $0x7f, %eax
jne 0xc9247
movq 0x10(%rsp), %rax
movl $0x9, 0x1fc(%rax)
leaq 0x2d7f5(%rip), %rdi     # 0xf6a35
movb $0x0, %al
callq 0x94bf0
movq 0x10(%rsp), %rax
movl $0xa, 0x1fc(%rax)
movl 0x2024(%rsp), %esi
leaq 0x2d803(%rip), %rdi     # 0xf6a67
movb $0x0, %al
callq 0x94bf0
jmp 0xc926d
movq 0x10(%rsp), %rdi
callq 0xa2f30
cmpl $0x1, %eax
je 0xc9293
movq 0x10(%rsp), %rdi
callq 0xa2f30
movl %eax, %ecx
movq 0x10(%rsp), %rax
movl %ecx, 0x1fc(%rax)
movq (%rsp), %rdi
movq 0x10(%rsp), %rsi
addq $0x198, %rsi            # imm = 0x198
callq 0xc9500
movq 0x8(%rsp), %rax
addq $0x20c8, %rsp           # imm = 0x20C8
retq
nopw %cs:(%rax,%rax)
nop