// File: /workspace/github_cpp_makefile_star2_O3/davmac314[P]dinit/src/proc-service.cc
// Function: bgproc_service::handle_exit_status()
void bgproc_service::handle_exit_status() noexcept
{
    // For bgproc services, receiving exit status can mean one of two things:
    // 1. We were launching the process, and it finished (possibly after forking). If it did fork
    //    we want to obtain the process id of the process that we should now monitor, the actual
    //    daemon. Or,
    // 2. The above has already happened, and we are monitoring the daemon process, which has now
    //    terminated for some reason.

    begin:
    bool did_exit = exit_status.did_exit();
    bool was_signalled = exit_status.was_signalled();
    auto current_state = get_state();

    if (!exit_status.did_exit_clean() && current_state != service_state_t::STOPPING) {
        if (did_exit) {
            log(loglevel_t::ERROR, "Service ", get_name(), " process terminated with exit code ",
                    exit_status.get_exit_status());
        }
        else if (was_signalled) {
            log(loglevel_t::ERROR, "Service ", get_name(), " terminated due to signal ",
                    exit_status.get_signal());
        }
    }

    if (waiting_stopstart_timer) {
        process_timer.stop_timer(event_loop);
        waiting_stopstart_timer = false;
    }

    if (doing_smooth_recovery) {
        doing_smooth_recovery = false;

        // We're either started, or stopping (i.e. we were requested to stop during smooth recovery).

        if (current_state == service_state_t::STOPPING) {
            // Stop was issued during smooth recovery
            if ((did_exit && exit_status.get_exit_status() != 0) || was_signalled) {
                if (!waiting_for_deps) {
                    stopped();
                }
                else if (get_target_state() == service_state_t::STARTED && !pinned_stopped) {
                    initiate_start();
                }
            }
            else {
                // We need to re-read the PID, since it has now changed.
                if (pid_file.length() != 0) {
                    auto pid_result = read_pid_file(&exit_status);

                    if (waiting_for_deps) {
                        // don't do anything else until dependents have stopped
                        return;
                    }

                    switch (pid_result) {
                    case pid_result_t::FAILED:
                    case pid_result_t::TERMINATED:
                        // Failed startup: no auto-restart.
                        stopped();
                        break;
                    case pid_result_t::OK:
                        // We now need to bring down the daemon process
                        bring_down();
                        break;
                    }
                }
            }
            services->process_queues();
            return;
        }
        else /* if (service_state == service_state_t::STARTED) */ {
            bool need_stop = false;
            if ((did_exit && exit_status.get_exit_status() != 0) || was_signalled) {
                need_stop = true;
            }
            else {
                // We need to re-read the PID, since it has now changed.
                if (pid_file.length() != 0) {
                    auto pid_result = read_pid_file(&exit_status);

                    switch (pid_result) {
                    case pid_result_t::FAILED:
                        // Failed startup: no auto-restart.
                        need_stop = true;
                        break;
                    case pid_result_t::TERMINATED:
                        goto begin;
                    case pid_result_t::OK:
                        break;
                    }
                }
            }

            if (need_stop) {
                // Failed startup: no auto-restart.
                stop_reason = stopped_reason_t::TERMINATED;
                unrecoverable_stop();
                services->process_queues();
            }

            return;
        }
    }

    if (current_state == service_state_t::STARTING) {
        if (exit_status.did_exit_clean()) {
            auto pid_result = read_pid_file(&exit_status);
            switch (pid_result) {
                case pid_result_t::FAILED:
                    // Failed startup: no auto-restart.
                    stop_reason = stopped_reason_t::FAILED;
                    failed_to_start();
                    break;
                case pid_result_t::TERMINATED:
                    // started, but immediately terminated
                    started();
                    goto begin;
                case pid_result_t::OK:
                    started();
                    break;
            }
        }
        else {
            stop_reason = stopped_reason_t::FAILED;
            failed_to_start();
        }
    }
    else if (current_state == service_state_t::STOPPING) {
        // We won't log a non-zero exit status or termination due to signal here -
        // we assume that the process died because we signalled it.
        if (stop_pid == -1 && !waiting_for_execstat) {
            stop_issued = false;
            stopped();
        }
    }
    else {
        // we must be STARTED
        if (smooth_recovery && get_target_state() == service_state_t::STARTED && check_restart()) {
            doing_smooth_recovery = true;
            do_smooth_recovery();
            if (get_state() != service_state_t::STARTED) {
                doing_smooth_recovery = false;
            }
            return;
        }
        handle_unexpected_termination();
    }
    services->process_queues();
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
movq %rdi, %rbx
leaq 0x4dc(%rdi), %r14
leaq 0x3d0(%rdi), %rax
movq %rax, (%rsp)
movl 0x4dc(%rbx), %r12d
movl 0x4e0(%rbx), %r13d
movzbl 0x2c(%rbx), %ebp
cmpl $0x3, %ebp
sete %al
testl %r13d, %r13d
sete %cl
orb %al, %cl
jne 0x24880
movl $0x3, %edi
leaq 0x1121e(%rip), %rsi     # 0x35a4f
callq 0x2e412
movq 0x8(%rbx), %rdi
callq 0x2e520
cmpl $0x1, %r12d
je 0x2484e
leaq 0x112ee(%rip), %rdi     # 0x35b3a
jmp 0x24855
leaq 0x1123e(%rip), %rdi     # 0x35a93
callq 0x2e520
movl $0xc, %esi
leaq 0xc(%rsp), %r15
movq %r15, %rdi
leaq 0x11f3e(%rip), %rdx     # 0x367ac
movl %r13d, %ecx
xorl %eax, %eax
callq 0x89e0
movq %r15, %rdi
callq 0x2e53c
testb $0x2, 0x4f4(%rbx)
je 0x248a6
movl 0x3fc(%rbx), %edx
leaq 0x2219a(%rip), %rdi     # 0x46a30
movq (%rsp), %rsi
callq 0x25f62
andb $-0x3, 0x4f4(%rbx)
cmpb $0x1, 0x5b8(%rbx)
jne 0x248fc
xorl $0x1, %r12d
orl 0x4e0(%rbx), %r12d
setne %al
movb $0x0, 0x5b8(%rbx)
cmpl $0x3, %ebp
je 0x249a1
testb %al, %al
jne 0x2498a
cmpq $0x0, 0x5f8(%rbx)
je 0x24a57
movq %rbx, %rdi
movq %r14, %rsi
callq 0x24a76
cmpl $0x2, %eax
je 0x24803
jmp 0x24981
cmpl $0x1, %ebp
jne 0x24956
cmpl $0x0, 0x4e0(%rbx)
jne 0x24938
movq %rbx, %rdi
movq %r14, %rsi
callq 0x24a76
cmpl $0x2, %eax
jne 0x24927
movq %rbx, %rdi
callq 0x23690
jmp 0x24803
testl %eax, %eax
je 0x24a09
cmpl $0x1, %eax
jne 0x24a4b
movl $0x3, 0x1c4(%rbx)
movq %rbx, %rdi
xorl %esi, %esi
movl $0x1, %edx
callq 0x23316
jmp 0x24a4b
cmpl $0x3, %ebp
jne 0x249cf
cmpl $-0x1, 0x504(%rbx)
jne 0x24a4b
testb $-0x80, 0x10c(%rbx)
jne 0x24a4b
andb $-0x3, 0x500(%rbx)
jmp 0x24a43
cmpl $0x1, %eax
jne 0x24a57
movl $0x6, 0x1c4(%rbx)
movq %rbx, %rdi
callq 0x23762
jmp 0x24a4b
testb %al, %al
je 0x24a1d
movl 0x10c(%rbx), %eax
testb $0x10, %al
je 0x24a43
testb $0x2, %al
jne 0x24a4b
cmpb $0x2, 0x2d(%rbx)
jne 0x24a4b
movq %rbx, %rdi
callq 0x22b3a
jmp 0x24a4b
testb $0x1, 0x10c(%rbx)
je 0x24a13
cmpb $0x2, 0x2d(%rbx)
jne 0x24a13
movq (%rbx), %rax
movq %rbx, %rdi
callq *0x28(%rax)
testb %al, %al
je 0x24a13
movb $0x1, 0x5b8(%rbx)
movq %rbx, %rdi
callq 0x2652c
cmpb $0x2, 0x2c(%rbx)
je 0x24a57
movb $0x0, 0x5b8(%rbx)
jmp 0x24a57
movq %rbx, %rdi
callq 0x23690
jmp 0x24a4b
movq %rbx, %rdi
callq 0x2716c
jmp 0x24a4b
cmpq $0x0, 0x5f8(%rbx)
je 0x24a4b
movq %rbx, %rdi
movq %r14, %rsi
callq 0x24a76
testb $0x10, 0x10c(%rbx)
jne 0x24a57
leal -0x1(%rax), %ecx
cmpl $0x2, %ecx
jae 0x24a66
movq %rbx, %rdi
callq 0x22792
movq 0x148(%rbx), %rdi
callq 0xd37e
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
testl %eax, %eax
jne 0x24a4b
movq (%rbx), %rax
movq %rbx, %rdi
callq *0x8(%rax)
jmp 0x24a4b
nop