// File: davmac314[P]dinit/src/proc-service.cc
// Function: scripted_service::handle_exit_status()
void scripted_service::handle_exit_status() noexcept
{
    bool did_exit = exit_status.did_exit();
    bool was_signalled = exit_status.was_signalled();
    auto current_state = get_state();

    // For a scripted service, a termination occurs in one of three main cases:
    // - the start script completed (or failed), when service was STARTING
    // - the start script was interrupted to cancel startup; state is STOPPING
    // - the stop script complete (or failed), state is STOPPING

    if (current_state == service_state_t::STOPPING) {
        // We might be running the stop script, or we might be running the start script and have issued
        // a cancel order via SIGINT:
        if (interrupting_start) {
            if (waiting_stopstart_timer) {
                process_timer.stop_timer(event_loop);
                waiting_stopstart_timer = false;
            }
            // We issued a start interrupt, so we expected this failure:
            if (did_exit && exit_status.get_exit_status() != 0) {
                log(loglevel_t::NOTICE, "Service ", get_name(), " start cancelled; exit code ",
                        exit_status.get_exit_status());
                // Assume that a command terminating normally (with failure status) requires no cleanup:
                stopped();
            }
            else {
                if (was_signalled) {
                    log(loglevel_t::NOTICE, "Service ", get_name(), " start cancelled from signal ",
                            exit_status.get_signal());
                }
                // If the start script completed successfully, or was interrupted via our signal,
                // we want to run the stop script to clean up:
                bring_down();
            }
            interrupting_start = false;
        }
        else if (exit_status.did_exit_clean()) {
            // We were running the stop script and finished successfully
            stopped();
        }
        else {
            // ??? failed to stop! Let's log it as warning:
            if (did_exit) {
                log(loglevel_t::WARN, "Service ", get_name(), " stop command failed with exit code ",
                        exit_status.get_exit_status());
            }
            else if (was_signalled) {
                log(loglevel_t::WARN, "Service ", get_name(), " stop command terminated due to signal ",
                        exit_status.get_signal());
            }
            // Even if the stop script failed, assume that service is now stopped, so that any dependencies
            // can be stopped. There's not really any other useful course of action here.
            stopped();
        }
        services->process_queues();
    }
    else { // STARTING
        if (exit_status.did_exit_clean()) {
            started();
        }
        else if (was_signalled && exit_status.get_signal() == SIGINT && onstart_flags.skippable) {
            // A skippable service can be skipped by interrupting (eg by ^C if the service
            // starts on the console).
            start_skipped = true;
            started();
        }
        else {
            // failed to start
            if (did_exit) {
                log(loglevel_t::ERROR, "Service ", get_name(), " command failed with exit code ",
                        exit_status.get_exit_status());
            }
            else if (was_signalled) {
                log(loglevel_t::ERROR, "Service ", get_name(), " command terminated due to signal ",
                        exit_status.get_signal());
            }
            stop_reason = stopped_reason_t::FAILED;
            failed_to_start();
        }
        services->process_queues();
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x60, %rsp
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rdi
movq %rdi, -0x30(%rbp)
addq $0x4dc, %rdi            # imm = 0x4DC
callq 0x4ed70
movq -0x30(%rbp), %rdi
andb $0x1, %al
movb %al, -0x9(%rbp)
addq $0x4dc, %rdi            # imm = 0x4DC
callq 0x4e4b0
movq -0x30(%rbp), %rdi
andb $0x1, %al
movb %al, -0xa(%rbp)
callq 0x2f0d0
movb %al, -0xb(%rbp)
cmpb $0x3, -0xb(%rbp)
jne 0x51148
movq -0x30(%rbp), %rax
movb 0x500(%rax), %al
andb $0x1, %al
testb $0x1, %al
je 0x51074
movq -0x30(%rbp), %rax
movb 0x4f4(%rax), %al
shrb %al
andb $0x1, %al
testb $0x1, %al
je 0x50fa3
movq -0x30(%rbp), %rdi
addq $0x3b0, %rdi            # imm = 0x3B0
leaq 0x57bd8(%rip), %rsi     # 0xa8b60
callq 0x529f0
movq -0x30(%rbp), %rax
movb 0x4f4(%rax), %cl
andb $-0x3, %cl
orb $0x0, %cl
movb %cl, 0x4f4(%rax)
testb $0x1, -0x9(%rbp)
je 0x51009
movq -0x30(%rbp), %rdi
addq $0x4dc, %rdi            # imm = 0x4DC
callq 0x4e590
cmpl $0x0, %eax
je 0x51009
movq -0x30(%rbp), %rdi
callq 0x2d420
movq -0x30(%rbp), %rdi
movq %rax, -0x38(%rbp)
addq $0x4dc, %rdi            # imm = 0x4DC
callq 0x4e590
movq -0x38(%rbp), %rdx
movl %eax, -0x10(%rbp)
movl $0x1, %edi
leaq 0x27a21(%rip), %rsi     # 0x78a0f
leaq 0x27a98(%rip), %rcx     # 0x78a8d
leaq -0x10(%rbp), %r8
callq 0x51290
movq -0x30(%rbp), %rdi
callq 0x4bb20
jmp 0x51059
testb $0x1, -0xa(%rbp)
je 0x5104f
movq -0x30(%rbp), %rdi
callq 0x2d420
movq -0x30(%rbp), %rdi
movq %rax, -0x40(%rbp)
addq $0x4dc, %rdi            # imm = 0x4DC
callq 0x4e500
movq -0x40(%rbp), %rdx
movl %eax, -0x14(%rbp)
movl $0x1, %edi
leaq 0x279d0(%rip), %rsi     # 0x78a0f
leaq 0x27a64(%rip), %rcx     # 0x78aaa
leaq -0x14(%rbp), %r8
callq 0x512d0
movq -0x30(%rbp), %rdi
movq (%rdi), %rax
callq *0x8(%rax)
movq -0x30(%rbp), %rax
movb 0x500(%rax), %cl
andb $-0x2, %cl
orb $0x0, %cl
movb %cl, 0x500(%rax)
jmp 0x51133
movq -0x30(%rbp), %rdi
addq $0x4dc, %rdi            # imm = 0x4DC
callq 0x4e260
testb $0x1, %al
jne 0x5108a
jmp 0x51098
movq -0x30(%rbp), %rdi
callq 0x4bb20
jmp 0x51131
testb $0x1, -0x9(%rbp)
je 0x510e0
movq -0x30(%rbp), %rdi
callq 0x2d420
movq -0x30(%rbp), %rdi
movq %rax, -0x48(%rbp)
addq $0x4dc, %rdi            # imm = 0x4DC
callq 0x4e590
movq -0x48(%rbp), %rdx
movl %eax, -0x18(%rbp)
movl $0x2, %edi
leaq 0x27941(%rip), %rsi     # 0x78a0f
leaq 0x279f3(%rip), %rcx     # 0x78ac8
leaq -0x18(%rbp), %r8
callq 0x51310
jmp 0x51128
testb $0x1, -0xa(%rbp)
je 0x51126
movq -0x30(%rbp), %rdi
callq 0x2d420
movq -0x30(%rbp), %rdi
movq %rax, -0x50(%rbp)
addq $0x4dc, %rdi            # imm = 0x4DC
callq 0x4e500
movq -0x50(%rbp), %rdx
movl %eax, -0x1c(%rbp)
movl $0x2, %edi
leaq 0x278f9(%rip), %rsi     # 0x78a0f
leaq 0x279d0(%rip), %rcx     # 0x78aed
leaq -0x1c(%rbp), %r8
callq 0x51350
jmp 0x51128
movq -0x30(%rbp), %rdi
callq 0x4bb20
jmp 0x51133
movq -0x30(%rbp), %rax
movq 0x148(%rax), %rdi
callq 0x173c0
jmp 0x5127d
movq -0x30(%rbp), %rdi
addq $0x4dc, %rdi            # imm = 0x4DC
callq 0x4e260
testb $0x1, %al
jne 0x5115e
jmp 0x5116c
movq -0x30(%rbp), %rdi
callq 0x4d570
jmp 0x5126d
testb $0x1, -0xa(%rbp)
je 0x511c1
movq -0x30(%rbp), %rdi
addq $0x4dc, %rdi            # imm = 0x4DC
callq 0x4e500
cmpl $0x2, %eax
jne 0x511c1
movq -0x30(%rbp), %rax
movw 0x2e(%rax), %ax
shrw $0x8, %ax
andw $0x1, %ax
testw $0x1, %ax
je 0x511c1
movq -0x30(%rbp), %rdi
movl 0x10c(%rdi), %eax
andl $0xfffeffff, %eax       # imm = 0xFFFEFFFF
orl $0x10000, %eax          # imm = 0x10000
movl %eax, 0x10c(%rdi)
callq 0x4d570
jmp 0x5126b
testb $0x1, -0x9(%rbp)
je 0x51209
movq -0x30(%rbp), %rdi
callq 0x2d420
movq -0x30(%rbp), %rdi
movq %rax, -0x58(%rbp)
addq $0x4dc, %rdi            # imm = 0x4DC
callq 0x4e590
movq -0x58(%rbp), %rdx
movl %eax, -0x20(%rbp)
movl $0x3, %edi
leaq 0x27818(%rip), %rsi     # 0x78a0f
leaq 0x278cf(%rip), %rcx     # 0x78acd
leaq -0x20(%rbp), %r8
callq 0x51390
jmp 0x51251
testb $0x1, -0xa(%rbp)
je 0x5124f
movq -0x30(%rbp), %rdi
callq 0x2d420
movq -0x30(%rbp), %rdi
movq %rax, -0x60(%rbp)
addq $0x4dc, %rdi            # imm = 0x4DC
callq 0x4e500
movq -0x60(%rbp), %rdx
movl %eax, -0x24(%rbp)
movl $0x3, %edi
leaq 0x277d0(%rip), %rsi     # 0x78a0f
leaq 0x278ac(%rip), %rcx     # 0x78af2
leaq -0x24(%rbp), %r8
callq 0x513d0
jmp 0x51251
movq -0x30(%rbp), %rdi
movl $0x3, 0x1c4(%rdi)
xorl %esi, %esi
movl $0x1, %edx
callq 0x4cf90
jmp 0x5126d
movq -0x30(%rbp), %rax
movq 0x148(%rax), %rdi
callq 0x173c0
addq $0x60, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)