Help us measure site usage?

With your permission, we use self-hosted analytics to understand page usage. It is optional and does not affect the Service. Learn more.

CadvancedbackendAI generated

Thread Pool HTTP Server

Build an HTTP server in C that serves files using a fixed pool of worker threads: the main thread accepts connections and puts them on a bounded queue, and the workers take connections from the queue and handle them. When the queue is full, new connections are refused politely with 503 instead of piling up, and on shutdown the server stops accepting, lets workers finish what they're doing, and exits cleanly. It parses requests carefully, blocks path traversal, supports keep-alive, and logs every request. Run it only on your own machine. You'll learn POSIX threads, mutexes and condition variables, designing a bounded queue, backpressure, signal handling in threaded programs, and testing concurrent C code with sanitizers.

Estimate
~14h
Steps
7
Completed by
0
Proposed by
codeseed.app

Make · POSIX · CMake

Project roadmap

  1. 01

    Design the server

    ~2h

    Write DESIGN.md: the accept loop, the bounded queue of client sockets (a ring buffer with a mutex and two condition variables, not empty and not full), the worker threads, what happens when the queue is full (reply 503 and close), the timeouts (read and keep-alive idle), and the shutdown sequence (a signal sets a flag, the accept loop stops, workers finish their current request and exit, and main joins them). Set up the build with Make or CMake using -Wall -Wextra -pthread. Done when: DESIGN.md covers every component and the shutdown sequence.

  2. 02

    Build the bounded queue

    ~2h

    Implement the queue: push (waits while full, or a try version that fails immediately), pop (waits while empty, and returns a special value when shutting down), and a shutdown function that wakes all waiting threads. Test it alone with several producer and consumer threads. Done when: a stress test passes millions of items through the queue without losing or duplicating any, with no errors under ThreadSanitizer.

  3. 03

    Serve HTTP requests

    ~3h

    In each worker, read the request until the end of the headers with a size limit, parse the request line and headers carefully, and serve GET and HEAD for files under the document root (resolved with realpath and checked against the root, returning 403 otherwise), with Content-Type, Content-Length, and 400, 404, 405 and 500 errors. Handle partial writes by looping until every byte is sent. Done when: a browser can load a small website from the server.

  4. 04

    Add keep-alive and limits

    ~2h

    Support HTTP/1.1 keep-alive: after a response, the worker reads the next request on the same connection until the client closes, an idle timeout passes (SO_RCVTIMEO), or a request limit is reached. When the queue is full, the accept loop replies 503 with Retry-After and closes. Done when: several requests reuse one connection, and overload produces 503 responses instead of hanging.

  5. 05

    Shut down gracefully

    ~1.5h

    Handle SIGINT and SIGTERM by setting a flag (with sigaction, keeping the handler minimal), closing the listening socket, shutting down the queue so workers wake up, and joining all workers after they finish their current requests. Ignore SIGPIPE so a disconnected client doesn't kill the server. Done when: Ctrl+C during load finishes in-flight requests and exits with no leaks under valgrind.

  6. 06

    Log and observe

    ~1h

    Log one line per request (time, client IP, method, path, status, bytes and duration) with a mutex protecting the log file, and keep counters (requests, 503s and active connections) with atomic operations, printed on shutdown or on SIGUSR1. Done when: the log is complete and never has mixed lines under load.

  7. 07

    Test and measure

    ~2.5h

    Write a test script with curl for normal files, errors, traversal attempts (--path-as-is), keep-alive and HEAD. Load test on your own machine with wrk or ab, trying different numbers of workers and queue sizes, and record the throughput and 503 rates in README.md. Run the tests under ThreadSanitizer and AddressSanitizer. Done when: all tests pass with no sanitizer errors, and README.md shows the measurements.

Ready to build this?

Get a GitHub repo and start building. Your AI reviewer checks each step as you go.

~14h · 7 steps

Tech stack

MakePOSIXCMake