// File: /workspace/github_c_makefile_star2_O3/motet-a[P]libforks/libforks.c
// Function: serv_main
__attribute__((noreturn))
static void serv_main(serv_Client *first_client) {
  serv_DEBUG("starting fork server (pid %d)\n", (int)getpid());
  serv_DEBUG("the main client's pid is %d\n", (int)first_client->pid);

  if (signal(SIGPIPE, SIG_IGN)) {
    serv_print_errno(NULL);
    serv_panic();
  }

  if (pipe(serv_exit_pipe) == -1) {
    serv_print_errno("pipe");
    serv_panic();
  }

  // Ignore SIGTERM.
  // Some container environments send SIGTERM to all processes
  // when terminating. It is up to the main process to stop the
  // fork server and its children properly.
  struct sigaction sa;
  sa.sa_handler = SIG_IGN;
  sa.sa_flags = 0;
  sigemptyset(&sa.sa_mask);
  if (sigaction(SIGTERM, &sa, NULL) == -1) {
      serv_print_errno(NULL);
      serv_panic();
  }

  // Stay notified of child exits through a SIGCHLD handler and `serv_exit_pipe`
  sa.sa_handler = serv_sigchld_handler;
  sa.sa_flags = SA_RESTART | SA_NOCLDSTOP;
  sigemptyset(&sa.sa_mask);
  if (sigaction(SIGCHLD, &sa, NULL) == -1) {
    serv_print_errno("sigaction");
    serv_panic();
  }

  size_t client_count = 1;

  while (true) {
    nfds_t fd_count = 1;

    struct pollfd poll_fds[1 + serv_MAX_CLIENTS];

    poll_fds[0].fd = serv_exit_pipe[READ_END];
    poll_fds[0].events = POLLIN | POLLPRI;
    poll_fds[0].revents = 0;

    for (serv_Client *c = first_client; c; c = c->next) {
      if (c->socket == -1) {
        continue; // “zombie” disconnected client
      }

      assert(fd_count <= (sizeof(poll_fds) / sizeof(struct pollfd)));
      struct pollfd *pollfd = poll_fds + fd_count;
      pollfd->fd = c->socket;
      pollfd->events = POLLIN | POLLPRI;
      pollfd->revents = 0;
      fd_count++;
    }

    serv_DEBUG("polling…\n");
    if (poll(poll_fds, fd_count, -1) == -1) {
      if (errno == EINTR) {
        serv_DEBUG("poll(2) has been interrupted by a signal\n");
        // poll failed because a signal has been received.
        // Just restart it.
        // (SA_RESTART does not work with poll(2))
        continue;
      }

      serv_print_errno("poll");
      serv_panic();
    }

    if (poll_fds[0].revents) {
      // A SIGCHLD signal has been received.

      assert(
        (poll_fds[0].revents & POLLIN) ||
        (poll_fds[0].revents & POLLPRI)
      );

      libforks_ExitEvent event;
      if (read_exact(serv_exit_pipe[READ_END], &event, sizeof event) == -1) {
        serv_print_errno("read_exact");
        serv_panic();
      }

      serv_DEBUG("main loop knows that %d has exited\n", (int)event.pid);

      serv_Client *client = serv_remove_client(&first_client, event.pid);
      assert(client);
      client_count--;

      if (client->exit_fd != -1) {
        serv_DEBUG("informing parent that %d has exited\n", (int)event.pid);
        if (write_exact(client->exit_fd, &event, sizeof event) == -1) {
          if (errno == EPIPE) {
            // Ignore the error because that’s pretty much normal and
            // expected, it happens if the client has closed the pipe
            // or exited.
            // (SIGPIPE is already ignored)
          } else {
            serv_print_errno("exit pipe write");
            serv_panic();
          }
        }
      }

      if (serv_connected_clients(first_client) == 0) {
        serv_DEBUG("no more connected clients, goodbye!\n");
        exit(0);
      }

      if (client->socket != -1) {
        close(client->socket);
      }
      if (client->exit_fd != -1) {
        close(client->exit_fd);
      }
      free(client);
    }

    for (size_t i = 1; i < fd_count; i++) {
      struct pollfd *pollfd = poll_fds + i;
      if (!pollfd->revents) {
        continue;
      }

      serv_Client *sender = serv_find_client_by_socket(
        first_client,
        pollfd->fd
      );
      if (!sender) {
        // the client has just exited and has been removed by the
        // libforks_ExitEvent handler
        continue;
      }

      if ((pollfd->revents & POLLERR) || (pollfd->revents & POLLNVAL)) {
        serv_print_error("socket read error (with client %d)",
            (int)sender->pid);
        serv_panic();
      }

      if (pollfd->revents & POLLHUP) {
        serv_DEBUG("client %d closed its socket\n", (int)sender->pid);
        // The sender may or may not have exited. We can’t forget it right
        // now because we may need its `exit_fd` to notify its parent
        // when it will actually exits, so we mark it as a “zombie” by
        // setting its `socket` to -1 and wait for a SIGCHLD signal.
        assert(sender->socket != -1);
        close(sender->socket);
        sender->socket = -1;
        if (serv_connected_clients(first_client) == 0) {
          serv_DEBUG("no more connected clients, goodbye!\n");
          exit(0);
        }
        continue;
      }

      assert(
        (pollfd->revents & POLLIN) ||
        (pollfd->revents & POLLPRI)
      );

      assert(sender->socket == pollfd->fd);
      ClientMessage req = serv_recv(pollfd->fd);
      serv_handle_request(&req, &first_client, &client_count, sender);
    }
  }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x1b8, %rsp            # imm = 0x1B8
movq %rdi, %rbp
movq %rdi, 0x10(%rsp)
movl $0x1, %esi
movl $0xd, %edi
callq 0x1100
testq %rax, %rax
jne 0x2172
leaq 0x3769(%rip), %rdi      # 0x5114
callq 0x10e0
cmpl $-0x1, %eax
je 0x2123
leaq 0x128(%rsp), %rbx
movq $0x1, -0x8(%rbx)
movl $0x0, 0x80(%rbx)
movq %rbx, %rdi
callq 0x1120
leaq 0x120(%rsp), %rsi
movl $0xf, %edi
xorl %edx, %edx
callq 0x1070
cmpl $-0x1, %eax
je 0x2172
leaq 0xb77(%rip), %rax       # 0x2576
leaq 0x120(%rsp), %r14
movq %rax, (%r14)
movl $0x10000001, 0x88(%r14) # imm = 0x10000001
movq %rbx, %rdi
callq 0x1120
movl $0x11, %edi
movq %r14, %rsi
xorl %edx, %edx
callq 0x1070
cmpl $-0x1, %eax
je 0x2179
movl $0x1, %eax
movq %rax, 0x18(%rsp)
leaq 0x70(%rsp), %rbx
leaq 0x40(%rsp), %r14
movl 0x36c5(%rip), %eax      # 0x5114
movl %eax, 0x70(%rsp)
movl $0x3, 0x74(%rsp)
movl $0x1, %r13d
testq %rbp, %rbp
je 0x1a95
movq %rbp, %rax
movl 0x8(%rax), %ecx
cmpl $-0x1, %ecx
je 0x1a8c
cmpq $0x16, %r13
jae 0x1f85
movl %ecx, 0x70(%rsp,%r13,8)
movl $0x3, 0x74(%rsp,%r13,8)
incq %r13
movq 0x10(%rax), %rax
testq %rax, %rax
jne 0x1a69
movq %rbx, %rdi
movq %r13, %rsi
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
callq 0x1180
cmpl $-0x1, %eax
je 0x1f6b
movzwl 0x76(%rsp), %eax
testw %ax, %ax
je 0x1b93
testb $0x3, %al
je 0x203b
movl 0x364a(%rip), %edi      # 0x5114
movl $0x8, %edx
movq %r14, %rsi
callq 0x163f
cmpl $-0x1, %eax
je 0x202a
testq %rbp, %rbp
je 0x1fa4
movl 0x40(%rsp), %ecx
leaq 0x10(%rsp), %rax
cmpl %ecx, (%rbp)
je 0x1b0c
movq (%rax), %rax
addq $0x10, %rax
movq 0x10(%rbp), %rbp
testq %rbp, %rbp
jne 0x1af2
jmp 0x1fa4
movq 0x10(%rbp), %rcx
movq %rcx, (%rax)
movl 0xc(%rbp), %edi
cmpl $-0x1, %edi
je 0x1b3b
movl $0x8, %edx
movq %r14, %rsi
callq 0x17cb
cmpl $-0x1, %eax
jne 0x1b3b
callq 0x1050
cmpl $0x20, (%rax)
jne 0x2082
movq 0x10(%rsp), %rax
testq %rax, %rax
je 0x216b
decq 0x18(%rsp)
xorl %ecx, %ecx
xorl %edx, %edx
cmpl $-0x1, 0x8(%rax)
setne %dl
addl %edx, %ecx
movq 0x10(%rax), %rax
testq %rax, %rax
jne 0x1b50
testl %ecx, %ecx
je 0x216b
movl 0x8(%rbp), %edi
cmpl $-0x1, %edi
je 0x1b79
callq 0x18ef
movl 0xc(%rbp), %edi
cmpl $-0x1, %edi
je 0x1b86
callq 0x18ef
movq %rbp, %rdi
callq 0x1030
movq 0x10(%rsp), %rbp
cmpq $0x2, %r13
jb 0x1f61
movl $0x1, %r15d
movzwl 0x76(%rsp,%r15,8), %eax
testl %eax, %eax
je 0x1f55
movl 0x70(%rsp,%r15,8), %edi
testl %edi, %edi
js 0x1fc3
movq %rbp, %r12
testq %rbp, %rbp
je 0x1bdc
cmpl %edi, 0x8(%r12)
je 0x1be3
movq 0x10(%r12), %r12
testq %r12, %r12
jne 0x1bc6
jmp 0x1f55
xorl %ebp, %ebp
jmp 0x1f55
testb $0x28, %al
jne 0x1feb
testb $0x10, %al
jne 0x1c5e
testb $0x3, %al
je 0x200b
movl $0x18, %edx
movq %r14, %rsi
callq 0x163f
cmpl $-0x1, %eax
je 0x2002
movl 0x50(%rsp), %eax
cmpq $0x4, %rax
ja 0x206f
leaq 0x14e6(%rip), %rcx      # 0x3108
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
cmpq $0x14, 0x18(%rsp)
jne 0x1cf9
movl 0x8(%r12), %edi
movl $0xfffffffd, %eax       # imm = 0xFFFFFFFD
leaq -0x4(%rax), %rsi
movl $0x1, %edx
callq 0x2726
movl $0x14, %eax
movq %rax, 0x18(%rsp)
jmp 0x1f55
callq 0x18ef
movl $0xffffffff, 0x8(%r12)  # imm = 0xFFFFFFFF
xorl %eax, %eax
movq %rbp, %rcx
xorl %edx, %edx
cmpl $-0x1, 0x8(%rcx)
setne %dl
addl %edx, %eax
movq 0x10(%rcx), %rcx
testq %rcx, %rcx
jne 0x1c71
testl %eax, %eax
jne 0x1f55
jmp 0x216b
movl 0x40(%rsp), %ebx
movq %rbp, %r14
cmpq %r12, %r14
je 0x1cbb
movl (%r14), %edi
movl %ebx, %esi
callq 0x1150
cmpl $-0x1, %eax
jne 0x1cbb
callq 0x1050
cmpl $0x3, (%rax)
jne 0x1fe2
movq 0x10(%r14), %r14
testq %r14, %r14
jne 0x1c99
movl 0x8(%r12), %edi
xorl %esi, %esi
movl $0x2, %edx
callq 0x2726
leaq 0x70(%rsp), %rbx
jmp 0x1f50
callq *0x40(%rsp)
movl 0x8(%r12), %edi
xorl %esi, %esi
movl $0x3, %edx
callq 0x2726
jmp 0x1f55
callq 0x1090
movl %eax, 0x34(%rsp)
movl $0x1, %edi
movl $0x1, %esi
xorl %edx, %edx
leaq 0x58(%rsp), %rcx
callq 0x1140
cmpl $-0x1, %eax
je 0x1e24
movl 0x58(%rsp), %eax
movl %eax, 0x8(%rsp)
movl 0x5c(%rsp), %eax
movl %eax, 0xc(%rsp)
movq $-0x1, 0x28(%rsp)
movl $0xffffffff, %r14d      # imm = 0xFFFFFFFF
cmpb $0x1, 0x40(%rsp)
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
jne 0x1d74
movl $0x1, %edi
movl $0x1, %esi
xorl %edx, %edx
leaq 0x28(%rsp), %rcx
callq 0x1140
cmpl $-0x1, %eax
je 0x1e84
movl 0x28(%rsp), %eax
movl 0x2c(%rsp), %r14d
movl %eax, 0x4(%rsp)
callq 0x11f0
cmpl $-0x1, %eax
je 0x1e46
movl %eax, %ebx
testl %eax, %eax
je 0x2094
movl 0xc(%rsp), %edi
callq 0x18ef
cmpl $-0x1, %r14d
je 0x1da7
movl %r14d, %edi
callq 0x18ef
movl $0x18, %edi
callq 0x1160
testq %rax, %rax
je 0x2117
movq %rax, %r14
movl %ebx, (%rax)
movb $0x0, 0x4(%rax)
movl 0x8(%rsp), %edi
movl %edi, 0x8(%rax)
movl $0xffffffff, 0xc(%rax)  # imm = 0xFFFFFFFF
movq %rbp, 0x10(%rax)
movq $-0x1, 0x20(%rsp)
cmpb $0x1, 0x41(%rsp)
jne 0x1e04
leaq 0x20(%rsp), %rdi
callq 0x10e0
cmpl $-0x1, %eax
je 0x2123
movl 0x24(%rsp), %eax
movl %eax, 0xc(%r14)
movl 0x8(%rsp), %edi
movl 0x4(%rsp), %eax
cmpl $-0x1, %eax
je 0x1ebb
movl %eax, 0x38(%rsp)
movl $0x1, %ebp
leaq 0x3c(%rsp), %rax
jmp 0x1ec2
callq 0x1050
movl (%rax), %esi
shlq $0x20, %rsi
movl $0xfffffffd, %eax       # imm = 0xFFFFFFFD
orq %rax, %rsi
movl 0x8(%r12), %edi
movl $0x1, %edx
jmp 0x1cef
callq 0x1050
movl (%rax), %eax
shlq $0x20, %rax
movl $0xfffffffd, %ecx       # imm = 0xFFFFFFFD
leaq -0x2(%rcx), %rsi
orq %rax, %rsi
movl 0x8(%r12), %edi
movl $0x1, %edx
callq 0x2726
movl 0x4(%rsp), %edi
callq 0x18ef
movl %r14d, %edi
callq 0x18ef
leaq 0x70(%rsp), %rbx
jmp 0x1ea6
callq 0x1050
movl (%rax), %esi
shlq $0x20, %rsi
movl $0xfffffffd, %eax       # imm = 0xFFFFFFFD
orq %rax, %rsi
movl 0x8(%r12), %edi
movl $0x1, %edx
callq 0x2726
movl 0x8(%rsp), %edi
callq 0x18ef
movq %rbp, %r14
movl 0xc(%rsp), %edi
jmp 0x1f48
leaq 0x38(%rsp), %rax
xorl %ebp, %ebp
movl 0x20(%rsp), %ecx
cmpl $-0x1, %ecx
je 0x1ed0
incq %rbp
movl %ecx, (%rax)
movl $0x1, %edx
leaq 0x3(%rsp), %rsi
callq 0x163f
cmpl $-0x1, %eax
je 0x202a
cmpb $0x72, 0x3(%rsp)
jne 0x202a
movl 0x8(%r12), %edi
movl %ebx, %eax
movq %rax, 0x60(%rsp)
movl $0x0, 0x68(%rsp)
movl $0xc, %edx
leaq 0x60(%rsp), %rsi
leaq 0x38(%rsp), %rcx
movq %rbp, %r8
callq 0x166f
cmpl $-0x1, %eax
je 0x208b
movl 0x20(%rsp), %edi
cmpl $-0x1, %edi
je 0x1f35
callq 0x18ef
incq 0x18(%rsp)
movl 0x4(%rsp), %edi
cmpl $-0x1, %edi
leaq 0x70(%rsp), %rbx
je 0x1f4d
callq 0x18ef
movq %r14, %rbp
leaq 0x40(%rsp), %r14
incq %r15
cmpq %r13, %r15
jne 0x1ba3
movq %rbp, 0x10(%rsp)
jmp 0x1a49
callq 0x1050
cmpl $0x4, (%rax)
je 0x1a49
leaq 0x15a7(%rip), %rdi      # 0x3527
jmp 0x2031
leaq 0x1546(%rip), %rdi      # 0x34d2
leaq 0x11fc(%rip), %rsi      # 0x318f
leaq 0x156f(%rip), %rcx      # 0x3509
movl $0x35a, %edx            # imm = 0x35A
callq 0x10b0
leaq 0x15ce(%rip), %rdi      # 0x3579
leaq 0x11dd(%rip), %rsi      # 0x318f
leaq 0x1550(%rip), %rcx      # 0x3509
movl $0x381, %edx            # imm = 0x381
callq 0x10b0
leaq 0x16bd(%rip), %rdi      # 0x3687
leaq 0x11be(%rip), %rsi      # 0x318f
leaq 0x16bb(%rip), %rcx      # 0x3693
movl $0x18f, %edx            # imm = 0x18F
callq 0x10b0
leaq 0x1765(%rip), %rdi      # 0x374e
jmp 0x2031
movl (%r12), %esi
leaq 0x159a(%rip), %rdi      # 0x3590
xorl %eax, %eax
callq 0x24b4
callq 0x24a0
leaq 0x16c6(%rip), %rdi      # 0x36cf
jmp 0x2031
leaq 0x15a1(%rip), %rdi      # 0x35b3
leaq 0x1176(%rip), %rsi      # 0x318f
leaq 0x14e9(%rip), %rcx      # 0x3509
movl $0x3ca, %edx            # imm = 0x3CA
callq 0x10b0
leaq 0x153d(%rip), %rdi      # 0x356e
callq 0x1900
callq 0x24a0
leaq 0x14ea(%rip), %rdi      # 0x352c
leaq 0x1146(%rip), %rsi      # 0x318f
leaq 0x14b9(%rip), %rcx      # 0x3509
movl $0x376, %edx            # imm = 0x376
callq 0x10b0
movq %rbp, 0x10(%rsp)
movq %rbp, %rdi
movq %r12, %rsi
callq 0x2636
callq 0x26d0
leaq 0x165e(%rip), %rdi      # 0x36d4
xorl %eax, %eax
callq 0x24b4
callq 0x24a0
leaq 0x14f7(%rip), %rdi      # 0x3580
jmp 0x2031
leaq 0x16d5(%rip), %rdi      # 0x3767
jmp 0x2031
movq %rbp, 0x10(%rsp)
movl 0x8(%rsp), %edi
callq 0x18ef
movl 0x4(%rsp), %edi
cmpl $-0x1, %edi
je 0x20b0
callq 0x18ef
movq 0x10(%rbp), %rbx
movl 0xc(%rbp), %edi
cmpl $-0x1, %edi
je 0x20c1
callq 0x18ef
movl 0x8(%rbp), %edi
cmpl $-0x1, %edi
je 0x20ce
callq 0x18ef
movq %rbp, %rdi
callq 0x1030
movq %rbx, %rbp
testq %rbx, %rbx
jne 0x20b0
movl 0x3030(%rip), %edi      # 0x5114
callq 0x18ef
movl 0x3029(%rip), %edi      # 0x5118
callq 0x18ef
movl $0xf, %edi
callq 0x26d8
movl $0x11, %edi
callq 0x26d8
movl $0x8, %edi
callq 0x1160
testq %rax, %rax
jne 0x212f
leaq 0x110a(%rip), %rdi      # 0x3228
jmp 0x2031
leaq 0x1399(%rip), %rdi      # 0x34c3
jmp 0x2031
movq %rax, %rbx
movl 0x34(%rsp), %eax
movl %eax, (%rbx)
movl 0xc(%rsp), %edi
movl %edi, 0x4(%rbx)
leaq 0x14cf(%rip), %rsi      # 0x3615
movl $0x1, %edx
callq 0x17cb
cmpl $-0x1, %eax
jne 0x2161
leaq 0x15ff(%rip), %rdi      # 0x375b
jmp 0x2031
movq %rbx, %rdi
movl %r14d, %esi
callq *0x48(%rsp)
xorl %edi, %edi
callq 0x11c0
xorl %edi, %edi
jmp 0x2031
leaq 0x1348(%rip), %rdi      # 0x34c8
jmp 0x2031