// File: davmac314[P]dinit/src/service.cc
// Function: service_record::stopped()
void service_record::stopped() noexcept
{
    if (have_console) {
        bp_sys::tcsetpgrp(0, bp_sys::getpgrp());
        release_console();
    }

    force_stop = false;

    // If we are to re-start, restarting should have been set true and desired_state should be STARTED.
    // (A restart could be cancelled via a separately issued stop, including via a shutdown).
    bool will_restart = desired_state == service_state_t::STARTED && !pinned_stopped;

    // If we won't restart, break soft dependencies now
    if (!will_restart) {
        for (auto dept : dependents) {
            if (!dept->is_hard()) {
                // waits-for or soft dependency:
                if (dept->waiting_on) {
                    dept->waiting_on = false;
                    dept->get_from()->dependency_started();
                }
                if (dept->holding_acq) {
                    dept->holding_acq = false;
                    // release without issuing stop, since we're called only when this
                    // service is already stopped/stopping:
                    release(false);
                }
            }
        }
    }

    for (auto & dependency : depends_on) {
        // we signal dependencies in case they are waiting for us to stop:
        dependency.get_to()->dependent_stopped();
    }

    service_state = service_state_t::STOPPED;

    if (will_restart) {
        // Desired state is "started".
        initiate_start();
    }
    else {
        becoming_inactive();

        if (start_explicit) {
            // If we were explicitly started, our required_by count must be at least 1. Use
            // release() to correctly release, mark inactive and release dependencies.
            start_explicit = false;
            release(false);
        }
        else if (required_by == 0) {
            // This can only be the case if we didn't have start_explicit, since required_by would
            // otherwise by non-zero. Since our release(s) above were with state != STOPPED, we now
            // must mark inactive (i.e. it won't have been done as part of the release).
            services->service_inactive(this);
        }
    }

    // Start failure will have been logged already, only log if we are stopped for other reasons:
    if (!start_failed) {
        log_service_stopped(service_name);

        // If this service chains to another, start the chained service now, if:
        // - this service self-terminated (rather than being stopped),
        // - ... successfully (i.e. exit code 0)
        // - this service won't restart, and
        // - a shutdown isn't in progress
        if ((onstart_flags.always_chain || (did_finish(stop_reason)
                && get_exit_status().did_exit_clean() && !will_restart))
                && !start_on_completion.empty() && !services->is_shutting_down()) {
            try {
                auto chain_to = services->load_service(start_on_completion.c_str());
                chain_to->start();
            }
            catch (service_load_exc &sle) {
                log(loglevel_t::ERROR, "Couldn't chain to service ", start_on_completion, ": ",
                        "couldn't load ", sle.service_name, ": ", sle.exc_description);
            }
            catch (std::bad_alloc &bae) {
                log(loglevel_t::ERROR, "Couldn't chain to service ", start_on_completion,
                        ": Out of memory");
            }
        }
    }
    notify_listeners(service_event_t::STOPPED);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xc0, %rsp
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x88(%rbp)
movl 0x10c(%rax), %eax
shrl $0x6, %eax
andl $0x1, %eax
testl $0x1, %eax
je 0x4bb67
callq 0xa1b0
movl %eax, %esi
xorl %edi, %edi
callq 0xaa80
movq -0x88(%rbp), %rdi
callq 0x4bfd0
movq -0x88(%rbp), %rcx
movb $0x0, 0x190(%rcx)
xorl %eax, %eax
cmpb $0x2, 0x2d(%rcx)
movb %al, -0x89(%rbp)
jne 0x4bb9d
movq -0x88(%rbp), %rax
movl 0x10c(%rax), %eax
shrl %eax
andl $0x1, %eax
xorb $-0x1, %al
movb %al, -0x89(%rbp)
movb -0x89(%rbp), %al
andb $0x1, %al
movb %al, -0x9(%rbp)
testb $0x1, -0x9(%rbp)
jne 0x4bc77
movq -0x88(%rbp), %rax
addq $0x130, %rax            # imm = 0x130
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rdi
callq 0x304d0
movq %rax, -0x20(%rbp)
movq -0x18(%rbp), %rdi
callq 0x30530
movq %rax, -0x28(%rbp)
leaq -0x20(%rbp), %rdi
leaq -0x28(%rbp), %rsi
callq 0x30500
testb $0x1, %al
jne 0x4bbf3
jmp 0x4bc75
leaq -0x20(%rbp), %rdi
callq 0x30590
movq (%rax), %rax
movq %rax, -0x30(%rbp)
movq -0x30(%rbp), %rdi
callq 0x4e1f0
movb %al, -0x8a(%rbp)
jmp 0x4bc14
movb -0x8a(%rbp), %al
testb $0x1, %al
jne 0x4bc65
jmp 0x4bc20
movq -0x30(%rbp), %rax
testb $0x1, 0x10(%rax)
je 0x4bc43
movq -0x30(%rbp), %rax
movb $0x0, 0x10(%rax)
movq -0x30(%rbp), %rdi
callq 0x30420
movq %rax, %rdi
callq 0x4c010
movq -0x30(%rbp), %rax
testb $0x1, 0x11(%rax)
je 0x4bc63
movq -0x88(%rbp), %rdi
movq -0x30(%rbp), %rax
movb $0x0, 0x11(%rax)
xorl %esi, %esi
callq 0x4c070
jmp 0x4bc65
jmp 0x4bc67
leaq -0x20(%rbp), %rdi
callq 0x306a0
jmp 0x4bbdd
jmp 0x4bc77
movq -0x88(%rbp), %rax
addq $0x118, %rax            # imm = 0x118
movq %rax, -0x38(%rbp)
movq -0x38(%rbp), %rdi
callq 0x30240
movq %rax, -0x40(%rbp)
movq -0x38(%rbp), %rdi
callq 0x30270
movq %rax, -0x48(%rbp)
leaq -0x40(%rbp), %rdi
leaq -0x48(%rbp), %rsi
callq 0x302a0
testb $0x1, %al
jne 0x4bcb5
jmp 0x4bcde
leaq -0x40(%rbp), %rdi
callq 0x302d0
movq %rax, -0x50(%rbp)
movq -0x50(%rbp), %rdi
callq 0x3cda0
movq %rax, %rdi
callq 0x4c190
leaq -0x40(%rbp), %rdi
callq 0x30330
jmp 0x4bca2
movq -0x88(%rbp), %rax
movb $0x0, 0x2c(%rax)
testb $0x1, -0x9(%rbp)
je 0x4bcfd
movq -0x88(%rbp), %rdi
callq 0x4c1e0
jmp 0x4bd6f
movq -0x88(%rbp), %rdi
movq (%rdi), %rax
callq *0x20(%rax)
movq -0x88(%rbp), %rax
movl 0x10c(%rax), %eax
shrl $0x8, %eax
andl $0x1, %eax
testl $0x1, %eax
je 0x4bd48
movq -0x88(%rbp), %rdi
movl 0x10c(%rdi), %eax
andl $0xfffffeff, %eax       # imm = 0xFFFFFEFF
orl $0x0, %eax
movl %eax, 0x10c(%rdi)
xorl %esi, %esi
callq 0x4c070
jmp 0x4bd6d
movq -0x88(%rbp), %rax
cmpl $0x0, 0x110(%rax)
jne 0x4bd6b
movq -0x88(%rbp), %rsi
movq 0x148(%rsi), %rdi
callq 0x4c260
jmp 0x4bd6d
jmp 0x4bd6f
movq -0x88(%rbp), %rax
movl 0x10c(%rax), %eax
shrl $0xf, %eax
andl $0x1, %eax
testl $0x1, %eax
jne 0x4bf98
movq -0x88(%rbp), %rdi
addq $0x8, %rdi
callq 0x4c280
movq -0x88(%rbp), %rax
movw 0x2e(%rax), %ax
shrw $0xa, %ax
andw $0x1, %ax
testw $0x1, %ax
jne 0x4be34
movq -0x88(%rbp), %rax
movl 0x1c4(%rax), %edi
callq 0x4e240
movb %al, -0x8b(%rbp)
jmp 0x4bdd0
movb -0x8b(%rbp), %cl
xorl %eax, %eax
testb $0x1, %cl
movb %al, -0x8c(%rbp)
jne 0x4bde8
jmp 0x4be71
movq -0x88(%rbp), %rdi
movq (%rdi), %rax
movq 0x50(%rax), %rax
callq *%rax
movq %rax, -0x98(%rbp)
jmp 0x4be01
movq -0x98(%rbp), %rax
movq %rax, -0x58(%rbp)
leaq -0x58(%rbp), %rdi
callq 0x4e260
movb %al, %cl
xorl %eax, %eax
testb $0x1, %cl
movb %al, -0x8c(%rbp)
jne 0x4be26
jmp 0x4be71
xorl %eax, %eax
testb $0x1, -0x9(%rbp)
movb %al, -0x8c(%rbp)
jne 0x4be71
movq -0x88(%rbp), %rdi
addq $0x1c8, %rdi            # imm = 0x1C8
callq 0xac70
movb %al, %cl
xorl %eax, %eax
testb $0x1, %cl
movb %al, -0x8c(%rbp)
jne 0x4be71
movq -0x88(%rbp), %rax
movq 0x148(%rax), %rdi
callq 0x4e280
xorb $-0x1, %al
movb %al, -0x8c(%rbp)
movb -0x8c(%rbp), %al
testb $0x1, %al
jne 0x4be80
jmp 0x4bf96
movq -0x88(%rbp), %rdi
movq 0x148(%rdi), %rax
movq %rax, -0xa8(%rbp)
addq $0x1c8, %rdi            # imm = 0x1C8
callq 0xa250
movq -0xa8(%rbp), %rdi
movq %rax, %rsi
movq (%rdi), %rax
movq 0x10(%rax), %rax
callq *%rax
movq %rax, -0xa0(%rbp)
jmp 0x4bebd
movq -0xa0(%rbp), %rax
movq %rax, -0x60(%rbp)
movq -0x60(%rbp), %rdi
callq 0x4c2b0
jmp 0x4bf49
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x68(%rbp)
movl %eax, -0x6c(%rbp)
movl -0x6c(%rbp), %eax
movl %eax, -0xac(%rbp)
movl $0x3, %ecx
cmpl %ecx, %eax
jne 0x4bf4b
movq -0x68(%rbp), %rdi
callq 0xa240
movq -0x88(%rbp), %rdx
movq %rax, -0x80(%rbp)
addq $0x1c8, %rdx            # imm = 0x1C8
movq -0x80(%rbp), %r9
movq %r9, %rcx
addq $0x20, %rcx
movq %rsp, %rax
movq %rcx, 0x8(%rax)
leaq 0x2ace1(%rip), %rcx     # 0x76c06
movq %rcx, (%rax)
leaq 0x2ca5a(%rip), %rsi     # 0x78989
leaq 0x2ca7e(%rip), %r8      # 0x789b4
movl $0x3, %edi
callq 0x4c370
callq 0xac30
jmp 0x4bf47
jmp 0x4bf49
jmp 0x4bf96
movl -0xac(%rbp), %eax
movl $0x2, %ecx
cmpl %ecx, %eax
jne 0x4bfba
movq -0x68(%rbp), %rdi
callq 0xa240
movq -0x88(%rbp), %rdx
movq %rax, -0x78(%rbp)
addq $0x1c8, %rdx            # imm = 0x1C8
leaq 0x2ca0d(%rip), %rsi     # 0x78989
leaq 0x2ca21(%rip), %rcx     # 0x789a4
movl $0x3, %edi
callq 0x4c330
callq 0xac30
jmp 0x4bf94
jmp 0x4bf49
jmp 0x4bf98
movq -0x88(%rbp), %rdi
movl $0x1, %esi
callq 0x4e2a0
addq $0xc0, %rsp
popq %rbp
retq
movq %rax, %rdi
callq 0xfa30
movq -0x68(%rbp), %rdi
callq 0xfa30
nopw %cs:(%rax,%rax)