view seobeo/os/s_linux_edge.c @ 117:b91f2dd6f84d

[PostDog] Fixed delete logic.
author June Park <parkjune1995@gmail.com>
date Wed, 07 Jan 2026 05:02:45 -0800
parents 48f260576059
children a8976a008a9d
line wrap: on
line source

#include <sys/epoll.h>
#include "seobeo/seobeo.h"


void *Seobeo_Web_Edge_Worker(void *vargs)
{
  WorkerArgs *args = vargs;
  const int max_events = 64;
  struct epoll_event events[max_events];

  // Each thread creates its own epoll to avoid race conditions
  int epfd = epoll_create1(0);
  if (epfd < 0) {
    perror("epoll_create1");
    return NULL;
  }

  // Add server socket to this thread's epoll
  struct epoll_event ev = {
    .events = EPOLLIN | EPOLLET,
    .data.ptr = args->srv
  };
  if (epoll_ctl(epfd, EPOLL_CTL_ADD, args->srv->socket, &ev) < 0) {
    perror("epoll_ctl ADD server");
    close(epfd);
    return NULL;
  }

  while (1) {
    int n = epoll_wait(epfd, events, max_events, -1);
    if (n < 0) {
      if (errno == EINTR) continue;
      perror("epoll_wait");
      continue;
    }

    for (int i = 0; i < n; i++) {
      Seobeo_Handle *phandle = events[i].data.ptr;

      if (phandle == args->srv) {
        // Accept all pending connections (edge-triggered mode)
        while (1) {
          Seobeo_Handle *p_cli_handle = Seobeo_Stream_Handle_Server_Accept(args->srv);
          if (!p_cli_handle) break;

          struct epoll_event client_ev = {
            .events = EPOLLIN | EPOLLET,
            .data.ptr = p_cli_handle
          };
          if (epoll_ctl(epfd, EPOLL_CTL_ADD, p_cli_handle->socket, &client_ev) < 0)
          {
            perror("epoll_ctl ADD client");
            Seobeo_Handle_Destroy(p_cli_handle);
          }
        }
      } else {
        // Remove from epoll first
        epoll_ctl(epfd, EPOLL_CTL_DEL, phandle->socket, NULL);

        // Handle request (this function destroys the handle internally)
        Seobeo_Web_HandleClientRequest(phandle, args->cache);
      }
    }
  }

  close(epfd);
  return NULL;
}

void Seobeo_Web_Edge(
    Seobeo_Handle *p_server_handle,
    int thread_count,
    Seobeo_Cache_Entry *p_html_cache)
{
  pthread_attr_t attr;
  pthread_attr_init(&attr);
  pthread_attr_setstacksize(&attr, 5 * 1024 * 1024); // 5 MB

  pthread_t threads[thread_count];
  for (int i = 0; i < thread_count; i++)
  {
    WorkerArgs *args = malloc(sizeof(WorkerArgs));
    *args = (WorkerArgs){ p_server_handle, p_html_cache };

    pthread_create(&threads[i], &attr, Seobeo_Web_Edge_Worker, args);
  }

  // Join threads instead of detaching for proper cleanup
  for (int i = 0; i < thread_count; i++)
    pthread_join(threads[i], NULL);

  pthread_attr_destroy(&attr);
}