// File: /workspace/github_c_makefile_star2_O1/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 $0x1c8, %rsp            # imm = 0x1C8
movq %rdi, 0x8(%rsp)
movl $0x1, %esi
movl $0xd, %edi
callq 0x1100
testq %rax, %rax
jne 0x2239
leaq 0x376c(%rip), %rdi      # 0x5114
callq 0x10e0
cmpl $-0x1, %eax
je 0x221d
leaq 0x138(%rsp), %rbx
movq $0x1, -0x8(%rbx)
movl $0x0, 0x80(%rbx)
movq %rbx, %rdi
callq 0x1120
leaq 0x130(%rsp), %rsi
movl $0xf, %edi
xorl %edx, %edx
callq 0x1070
cmpl $-0x1, %eax
je 0x2239
leaq 0xc41(%rip), %rax       # 0x263d
leaq 0x130(%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 0x2240
movl $0x1, %eax
movq %rax, 0x30(%rsp)
leaq 0x50(%rsp), %r14
movl 0x36cd(%rip), %eax      # 0x5114
movl %eax, 0x80(%rsp)
movl $0x3, 0x84(%rsp)
movq 0x8(%rsp), %rax
movl $0x1, %r13d
testq %rax, %rax
je 0x1a98
movl 0x8(%rax), %ecx
cmpl $-0x1, %ecx
je 0x1a92
cmpq $0x16, %r13
jae 0x1fa4
movl %ecx, 0x80(%rsp,%r13,8)
movl $0x3, 0x84(%rsp,%r13,8)
incq %r13
movq 0x10(%rax), %rax
jmp 0x1a64
leaq 0x80(%rsp), %rdi
movq %r13, %rsi
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
callq 0x1180
cmpl $-0x1, %eax
je 0x1b12
movzwl 0x86(%rsp), %eax
testw %ax, %ax
je 0x1bb0
testb $0x3, %al
je 0x20d1
movl 0x3643(%rip), %edi      # 0x5114
movl $0x8, %edx
movq %r14, %rsi
callq 0x163f
cmpl $-0x1, %eax
je 0x212c
movq 0x8(%rsp), %rbx
testq %rbx, %rbx
je 0x1b0e
movl 0x50(%rsp), %ecx
leaq 0x8(%rsp), %rax
cmpl %ecx, (%rbx)
je 0x1b25
movq (%rax), %rax
addq $0x10, %rax
movq 0x10(%rbx), %rbx
testq %rbx, %rbx
jne 0x1afa
xorl %ebx, %ebx
jmp 0x1b2c
callq 0x1050
cmpl $0x4, (%rax)
je 0x1a41
jmp 0x210f
movq 0x10(%rbx), %rcx
movq %rcx, (%rax)
testq %rbx, %rbx
je 0x20f0
movl 0xc(%rbx), %edi
cmpl $-0x1, %edi
je 0x1b5d
movl $0x8, %edx
movq %r14, %rsi
callq 0x17cb
cmpl $-0x1, %eax
jne 0x1b5d
callq 0x1050
cmpl $0x20, (%rax)
jne 0x211b
movq 0x8(%rsp), %rax
testq %rax, %rax
je 0x1fec
decq 0x30(%rsp)
xorl %ecx, %ecx
xorl %edx, %edx
cmpl $-0x1, 0x8(%rax)
setne %dl
addl %edx, %ecx
movq 0x10(%rax), %rax
testq %rax, %rax
jne 0x1b72
testl %ecx, %ecx
je 0x1fec
movl 0x8(%rbx), %edi
cmpl $-0x1, %edi
je 0x1b9b
callq 0x18ef
movl 0xc(%rbx), %edi
cmpl $-0x1, %edi
je 0x1ba8
callq 0x18ef
movq %rbx, %rdi
callq 0x1030
movq 0x8(%rsp), %rbp
cmpq $0x2, %r13
jb 0x1f9a
movl $0x1, %r15d
movzwl 0x86(%rsp,%r15,8), %eax
testl %eax, %eax
je 0x1e75
movl 0x80(%rsp,%r15,8), %edi
testl %edi, %edi
js 0x1fc3
movq %rbp, %r12
testq %rbp, %rbp
je 0x1bff
cmpl %edi, 0x8(%r12)
je 0x1c02
movq 0x10(%r12), %r12
testq %r12, %r12
jne 0x1bee
xorl %r12d, %r12d
testq %r12, %r12
je 0x1e75
testb $0x28, %al
jne 0x1ff3
testb $0x10, %al
jne 0x1c7d
testb $0x3, %al
je 0x207b
cmpl %edi, 0x8(%r12)
jne 0x2041
movl $0x18, %edx
movq %r14, %rsi
callq 0x163f
cmpl $-0x1, %eax
je 0x2065
movl 0x60(%rsp), %eax
cmpq $0x4, %rax
ja 0x20b9
leaq 0x14b3(%rip), %rcx      # 0x3108
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
cmpq $0x14, 0x30(%rsp)
jne 0x1d2f
movl 0x8(%r12), %edi
movl $0xfffffffd, %eax       # imm = 0xFFFFFFFD
leaq -0x4(%rax), %rsi
jmp 0x1e6b
movl 0x8(%r12), %edi
cmpl $-0x1, %edi
je 0x201d
callq 0x18ef
movl $0xffffffff, 0x8(%r12)  # imm = 0xFFFFFFFF
testq %rbp, %rbp
je 0x1fe7
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 0x1ca7
testl %eax, %eax
jne 0x1e75
jmp 0x1fe7
testq %rbp, %rbp
je 0x1cff
movl 0x50(%rsp), %ebx
movq %rbp, %r14
cmpq %r12, %r14
je 0x1cf6
movl (%r14), %edi
movl %ebx, %esi
callq 0x1150
cmpl $-0x1, %eax
jne 0x1cf6
callq 0x1050
cmpl $0x3, (%rax)
jne 0x200f
movq 0x10(%r14), %r14
testq %r14, %r14
jne 0x1cd4
movl 0x8(%r12), %edi
xorl %esi, %esi
movl $0x2, %edx
callq 0x27ed
leaq 0x50(%rsp), %r14
jmp 0x1e75
callq *0x50(%rsp)
movl 0x8(%r12), %edi
xorl %esi, %esi
movl $0x3, %edx
jmp 0x1e70
callq 0x1090
movl %eax, %ebx
movl $0x1, %edi
movl $0x1, %esi
xorl %edx, %edx
leaq 0x68(%rsp), %rcx
callq 0x1140
cmpl $-0x1, %eax
je 0x1e53
movl %ebx, 0x44(%rsp)
movl 0x68(%rsp), %eax
movl %eax, 0x18(%rsp)
movl 0x6c(%rsp), %ebx
movq $-0x1, 0x38(%rsp)
cmpb $0x1, 0x50(%rsp)
jne 0x1d94
movl $0x1, %edi
movl $0x1, %esi
xorl %edx, %edx
leaq 0x38(%rsp), %rcx
callq 0x1140
cmpl $-0x1, %eax
je 0x1ec6
movl %ebx, 0x20(%rsp)
movl 0x38(%rsp), %ebx
movl 0x3c(%rsp), %r14d
callq 0x11f0
cmpl $-0x1, %eax
je 0x1e86
movl %r14d, 0x24(%rsp)
movl %ebx, 0x1c(%rsp)
testl %eax, %eax
je 0x2149
movl %eax, %r14d
movl 0x20(%rsp), %edi
callq 0x18ef
movl 0x24(%rsp), %edi
cmpl $-0x1, %edi
je 0x1dda
callq 0x18ef
movl $0x18, %edi
callq 0x1160
testq %rax, %rax
je 0x2207
movq %rax, %rbx
movl %r14d, (%rax)
movb $0x0, 0x4(%rax)
movl 0x18(%rsp), %eax
movl %eax, 0x8(%rbx)
movl $0xffffffff, 0xc(%rbx)  # imm = 0xFFFFFFFF
movq %rbp, 0x10(%rbx)
movq $-0x1, 0x28(%rsp)
cmpb $0x1, 0x51(%rsp)
jne 0x1e33
leaq 0x28(%rsp), %rdi
callq 0x10e0
cmpl $-0x1, %eax
je 0x2218
movl 0x2c(%rsp), %eax
movl %eax, 0xc(%rbx)
movl 0x1c(%rsp), %eax
cmpl $-0x1, %eax
je 0x1efb
movl %eax, 0x48(%rsp)
movl $0x1, %ebp
leaq 0x4c(%rsp), %rax
jmp 0x1f02
callq 0x1050
movl (%rax), %esi
shlq $0x20, %rsi
movl $0xfffffffd, %eax       # imm = 0xFFFFFFFD
orq %rax, %rsi
movl 0x8(%r12), %edi
movl $0x1, %edx
callq 0x27ed
incq %r15
cmpq %r13, %r15
jne 0x1bc5
jmp 0x1f9a
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 0x27ed
movl %ebx, %edi
callq 0x18ef
movl %r14d, %edi
callq 0x18ef
leaq 0x50(%rsp), %r14
movl 0x20(%rsp), %ebx
jmp 0x1ee8
callq 0x1050
movl (%rax), %esi
shlq $0x20, %rsi
movl $0xfffffffd, %eax       # imm = 0xFFFFFFFD
orq %rax, %rsi
movl 0x8(%r12), %edi
movl $0x1, %edx
callq 0x27ed
movl 0x18(%rsp), %edi
callq 0x18ef
movl %ebx, %edi
movq %rbp, %rbx
jmp 0x1f8d
leaq 0x48(%rsp), %rax
xorl %ebp, %ebp
movl 0x28(%rsp), %ecx
cmpl $-0x1, %ecx
je 0x1f10
incq %rbp
movl %ecx, (%rax)
movl $0x1, %edx
movl 0x18(%rsp), %edi
leaq 0x17(%rsp), %rsi
callq 0x163f
cmpl $-0x1, %eax
je 0x2127
cmpb $0x72, 0x17(%rsp)
jne 0x2127
movl 0x8(%r12), %edi
movl %r14d, %eax
movq %rax, 0x70(%rsp)
movl $0x0, 0x78(%rsp)
movl $0xc, %edx
leaq 0x70(%rsp), %rsi
leaq 0x48(%rsp), %rcx
movq %rbp, %r8
callq 0x166f
cmpl $-0x1, %eax
je 0x2138
movl 0x28(%rsp), %edi
cmpl $-0x1, %edi
je 0x1f7a
callq 0x18ef
incq 0x30(%rsp)
movl 0x1c(%rsp), %edi
cmpl $-0x1, %edi
leaq 0x50(%rsp), %r14
je 0x1f92
callq 0x18ef
movq %rbx, %rbp
jmp 0x1e75
movq %rbp, 0x8(%rsp)
jmp 0x1a41
leaq 0x1527(%rip), %rdi      # 0x34d2
leaq 0x11dd(%rip), %rsi      # 0x318f
leaq 0x1550(%rip), %rcx      # 0x3509
movl $0x35a, %edx            # imm = 0x35A
callq 0x10b0
movq %rbp, 0x8(%rsp)
leaq 0x16ea(%rip), %rdi      # 0x36b9
leaq 0x11b9(%rip), %rsi      # 0x318f
leaq 0x16e8(%rip), %rcx      # 0x36c5
movl $0x18f, %edx            # imm = 0x18F
callq 0x10b0
movq %rbp, 0x8(%rsp)
xorl %edi, %edi
callq 0x11c0
movq %rbp, 0x8(%rsp)
movl (%r12), %esi
leaq 0x158d(%rip), %rdi      # 0x3590
xorl %eax, %eax
callq 0x257b
callq 0x2567
movq %rbp, 0x8(%rsp)
leaq 0x1765(%rip), %rdi      # 0x3780
jmp 0x2071
movq %rbp, 0x8(%rsp)
leaq 0x158a(%rip), %rdi      # 0x35b3
leaq 0x115f(%rip), %rsi      # 0x318f
leaq 0x14d2(%rip), %rcx      # 0x3509
movl $0x3bd, %edx            # imm = 0x3BD
callq 0x10b0
movq %rbp, 0x8(%rsp)
leaq 0x15b5(%rip), %rdi      # 0x3602
leaq 0x113b(%rip), %rsi      # 0x318f
leaq 0x14ae(%rip), %rcx      # 0x3509
movl $0x3cc, %edx            # imm = 0x3CC
callq 0x10b0
movq %rbp, 0x8(%rsp)
leaq 0x1690(%rip), %rdi      # 0x3701
callq 0x1900
callq 0x2567
movq %rbp, 0x8(%rsp)
leaq 0x1541(%rip), %rdi      # 0x35c8
leaq 0x1101(%rip), %rsi      # 0x318f
leaq 0x1474(%rip), %rcx      # 0x3509
movl $0x3ca, %edx            # imm = 0x3CA
callq 0x10b0
movq %rbp, 0x8(%rsp)
movq %rbp, %rdi
movq %r12, %rsi
callq 0x26fd
movq %rbp, 0x8(%rsp)
callq 0x2797
movq %rbp, 0x8(%rsp)
leaq 0x1641(%rip), %rdi      # 0x3706
xorl %eax, %eax
callq 0x257b
callq 0x2567
leaq 0x1454(%rip), %rdi      # 0x352c
leaq 0x10b0(%rip), %rsi      # 0x318f
leaq 0x1423(%rip), %rcx      # 0x3509
movl $0x376, %edx            # imm = 0x376
callq 0x10b0
leaq 0x1482(%rip), %rdi      # 0x3579
leaq 0x1091(%rip), %rsi      # 0x318f
leaq 0x1404(%rip), %rcx      # 0x3509
movl $0x381, %edx            # imm = 0x381
callq 0x10b0
leaq 0x1411(%rip), %rdi      # 0x3527
jmp 0x2071
leaq 0x145e(%rip), %rdi      # 0x3580
jmp 0x2071
movq %rbx, 0x8(%rsp)
leaq 0x143b(%rip), %rdi      # 0x356e
jmp 0x2071
movq %rbx, 0x8(%rsp)
leaq 0x1655(%rip), %rdi      # 0x3799
jmp 0x2071
movq %rbp, 0x8(%rsp)
movl 0x18(%rsp), %edi
callq 0x18ef
movl 0x1c(%rsp), %edi
cmpl $-0x1, %edi
movl 0x20(%rsp), %ebx
je 0x2169
callq 0x18ef
testq %rbp, %rbp
je 0x219c
movq 0x10(%rbp), %r14
movl 0xc(%rbp), %edi
cmpl $-0x1, %edi
je 0x217f
callq 0x18ef
movl 0x8(%rbp), %edi
cmpl $-0x1, %edi
je 0x218c
callq 0x18ef
movq %rbp, %rdi
callq 0x1030
movq %r14, %rbp
testq %r14, %r14
jne 0x216e
movl 0x2f72(%rip), %edi      # 0x5114
callq 0x18ef
movl 0x2f6b(%rip), %edi      # 0x5118
callq 0x18ef
movl $0xf, %edi
callq 0x279f
movl $0x11, %edi
callq 0x279f
movl $0x8, %edi
callq 0x1160
testq %rax, %rax
je 0x220c
movq %rax, %r14
movl 0x44(%rsp), %eax
movl %eax, (%r14)
movl %ebx, 0x4(%r14)
leaq 0x145d(%rip), %rsi      # 0x3647
movl $0x1, %edx
movl %ebx, %edi
callq 0x17cb
cmpl $-0x1, %eax
jne 0x2229
leaq 0x158b(%rip), %rdi      # 0x378d
jmp 0x2071
movq %rbp, 0x8(%rsp)
leaq 0x1015(%rip), %rdi      # 0x3228
jmp 0x2071
movq %rbp, 0x8(%rsp)
leaq 0x129f(%rip), %rdi      # 0x34c3
jmp 0x2071
movq %r14, %rdi
movl 0x24(%rsp), %esi
callq *0x58(%rsp)
jmp 0x1fec
xorl %edi, %edi
jmp 0x2071
leaq 0x1281(%rip), %rdi      # 0x34c8
jmp 0x2071