i have tried asking chatGPT, reading documentation, etc for days but have been unsuccesful at finding the root of the problem (am relatively new to c++)
RELEVANT INFORMATION: mint linux, g++ compiler, firefox used for testing
webserver.hpp:
#ifndef WEBSERVER_OBJ
#define WEBSERVER_OBJ
#ifndef THREAD_AMT
#define THREAD_AMT 4
#endif
//amount of clients allowed to queue inside socket buffer
#ifndef SOCK_BACKLOG
#define SOCK_BACKLOG 256
#endif
#include <iostream>
#include <fstream>
#include <vector>
#include <cstring>
#include <algorithm>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <atomic>
#include <sys/poll.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <unordered_map>
#include <map>
#define uint_64 unsigned long
#define uint_32 unsigned int
std::vector<pollfd> clients;
constexpr int buffer_size = 8192;
constexpr int optval = 1;
typedef struct {
    int socket_fd;
    std::string method;
    std::string path;
    std::string connection;
    std::unordered_map<std::string, std::string> cookies;
} headers;
typedef void (*route_item)(headers);
typedef struct {
    const char *request;
    int socket_fd;
} th_task;
// used by server_routes to compare string's in hashmap
struct const_str_cmp {
    bool operator()(const char* str1, const char* str2) const {
        return std::strcmp(str1, str2) < 0;
    }
};
int th_route(pollfd socket_fd);
//it works aight, dont fckin touch it
class thread_pool {
public:
    thread_pool(int thread_count) : thread_max(thread_count - 1), thread_running(true) {
        for (int i = 0; i < thread_max; i++)
        {
            slave.push_back(std::thread(&thread_pool::worker, this));
        }
    }
    unsigned int excv(pollfd fd) {
        std::unique_lock<std::mutex> lock(mtx);
        
        queue.push_back(fd);
        lock.unlock();
        cv.notify_one();
        return queue.size();
    }
    ~thread_pool() {
        {
            std::unique_lock<std::mutex> lock(mtx);
            thread_running = false;
        }
        cv.notify_all();
        for (std::thread& t : slave)
        {
            if (t.joinable())
                t.join();
        }
    }
private:
    std::vector<pollfd> queue;
    std::vector<std::thread> slave;
    int thread_max;
    bool thread_running;
    std::mutex mtx;
    std::condition_variable cv;
    void worker() {
        while (thread_running)
        {
            std::cout << "threadpool" << std::endl;
            std::unique_lock<std::mutex> lock(mtx);
            cv.wait(lock, [this] { return !queue.empty() || !thread_running; });
            if (!queue.empty())
            {
                pollfd tmp = queue.front();
                queue.erase(queue.begin());
                lock.unlock();
                          
                th_route(tmp);
            }
        }
    }
};
headers parse_http(const char* request) {
    std::cout << "parsing\n";
    headers httpRequest;
    std::string buffer(request);
    // find method
    int methodEnd = buffer.find(' ');
    if (methodEnd != std::string::npos) {
        httpRequest.method = buffer.substr(0, methodEnd);
    }
    // find path
    int pathStart = methodEnd + 1;
    int pathEnd = buffer.find(' ', pathStart);
    if (pathEnd != std::string::npos)
        httpRequest.path = buffer.substr(pathStart, pathEnd - pathStart);
    // find cookies (if any)
    int cookieStart = buffer.find("Cookie: ");
    if (cookieStart != std::string::npos) {
        cookieStart += 8; // Skip "Cookie: "
        int cookieEnd = buffer.find("\r\n", cookieStart);
        std::string cookies = buffer.substr(cookieStart, cookieEnd - cookieStart);
        int separatorPos = cookies.find(';');
        int keyValueSeparatorPos;
        while (separatorPos != std::string::npos) {
            std::string cookie = cookies.substr(0, separatorPos);
            keyValueSeparatorPos = cookie.find('=');
            if (keyValueSeparatorPos != std::string::npos) {
                std::string key = cookie.substr(0, keyValueSeparatorPos);
                std::string value = cookie.substr(keyValueSeparatorPos + 1);
                httpRequest.cookies[key] = value;
            }
            cookies.erase(0, separatorPos + 1);
            separatorPos = cookies.find(';');
        }
        keyValueSeparatorPos = cookies.find('=');
        if (keyValueSeparatorPos != std::string::npos) {
            std::string key = cookies.substr(0, keyValueSeparatorPos);
            std::string value = cookies.substr(keyValueSeparatorPos + 1);
            httpRequest.cookies[key] = value;
        }
    }
    // find connection header
    int connectionStart = buffer.find("Connection: ");
    if (connectionStart != std::string::npos) {
        connectionStart += 12; // Skip "Connection: "
        int connectionEnd = buffer.find("\r\n", connectionStart);
        httpRequest.connection = buffer.substr(connectionStart, connectionEnd - connectionStart);
    }
    return httpRequest;
}
// executed by thread pool, returns true if connection should be terminated
int th_route(pollfd socket_fd) {
    std::cout << socket_fd.fd << std::endl;
    socket_fd.revents == 0;
    return 0;
}
namespace lib_http {
    
    class app // yes this is copying py-flask design patterns
    {
    public:
        app(const char *addr, int port): th_pool(THREAD_AMT) {
            socket_fd = socket(AF_INET, SOCK_STREAM, 0);
            server.sin_port = htons(port);
            server.sin_family = AF_INET;                
            if (strcmp(addr, "0.0.0.0") == 0)
                server.sin_addr.s_addr = INADDR_ANY;
            else
                server.sin_addr.s_addr = inet_addr(addr);
            server_size = sizeof(server);
            std::cout << "port:"  <<setsockopt(socket_fd, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval)) << std::endl;
            //connection needs to be properly terminated for this to work
            if (bind(socket_fd, (struct sockaddr *)&server, sizeof(server)) == -1)
                throw std::runtime_error("Unable to bind socket\n");
            if (listen(socket_fd, SOCK_BACKLOG) == -1)
                throw std::runtime_error("Unable to listen on socket");
            
            std::cout << "Listening on port: " << port << std::endl;
        }
        int run() {
            th_flag.store(true);
            
            th_connection = std::thread(&lib_http::app::accept_handler, this);
            th_packets = std::thread(&lib_http::app::packet_handler, this);
            return 0;
        }
        void route(const char *Src, route_item Dst) {
            server_routes[Src] = Dst;           
        }
        void exit() { //close threads
            th_flag.store(false);
            if (th_connection.joinable())
                th_connection.join();
            if (th_packets.joinable())
                th_packets.join();
        }
    private:
        int socket_fd;
        
        struct sockaddr_in server;
        socklen_t server_size;
        std::atomic<bool> th_flag;
        thread_pool th_pool;
        std::thread th_connection;
        std::thread th_packets;
        std::mutex mtx;
        std::map<const char *, route_item, const_str_cmp> server_routes;
        int accept_handler() {
            std::cout << "Thread: (accept_handler) start\n";
            while (th_flag.load()) {
                int sock_buf;
                if ((sock_buf = accept(socket_fd, (struct sockaddr*)&server, &server_size)) == -1)
                    continue;
                std::cout << "Connection RECV: " << sock_buf << std::endl;
                mtx.lock();
                pollfd buffer = {sock_buf, POLLIN, 0};
                clients.push_back(buffer);
                
                mtx.unlock();
            }
            return 0;
        }
        int packet_handler() {
            std::cout << "Thread: (packet_handler) start\n";
            while (th_flag.load()) {
                mtx.lock();
                int res = poll(clients.data(), clients.size(), 5);
                //std::cout << "poll: " << res << std::endl;
                mtx.unlock();
                if (res > 0)  {
                std::cout << "size result: " << res << " || " <<  clients.size() << std::endl;
                    for (int i = 0; i<clients.size(); i++) {
                        if (clients[i].revents != 0) {
                            th_pool.excv(clients[i]);
                        }
                    }   
                }
            }
            return 0;
        }
            
    };
    //caller takes ownership
    std::string fetch(const char *path) {
        std::ifstream file(path, std::ios::in | std::ios::binary );
        
        if (file.is_open()){
            file.seekg(0, std::ios::end);
            long size_fd = file.tellg();
            file.seekg(0, std::ios::beg);
            char *tmp = new char[size_fd];
            std::memset(tmp, 0, size_fd);
            file.read(tmp, size_fd);
            file.close();
            
            std::cout << "not empty\n";
            std::string buffer(tmp);
            delete[] tmp;
            return buffer;
        }
        std::cout << "empty\n";
        return nullptr;
    }
}
#endif
main.cpp:
#include <iostream>
#include "webserver.hpp"
int main() {
    lib_http::app server("127.0.0.1", 5555);
    server.run();
    sleep(10);
    server.exit();
    return 0;
}
when i run it and try to connect to it from firefox webbrowser it shows the terminal output infinately:
threadpool
threadpool
port:threadpool0
Listening on port: 5555
Thread: (accept_handler) start
Thread: (packet_handler) start
Connection RECV: 4
size result: 1 || 1
4
threadpool
size result: 1 || 1
4
threadpool
size result: 1 || 1
4
threadpool
size result: 1 || 1
4
threadpool
size result: 1 || 1
4
threadpool
size result: 1 || 1
4
threadpool
size result: 1 || 1
4
threadpool
size result: 1 || 1
4
threadpool
size result: 1 || 1
4
threadpool
size result: 1 || 1
4
threadpool
size result: 1 || 1
4
threadpool
size result: 1 || 1
4
threadpool
size result: 1 || 1
4
threadpool
size result: 1 || 1
4
threadpool
size result: 1 || 1
4
threadpool
size result: 1 || 1
4
threadpool
size result: 1 || 1
4
threadpool
size result: 1 || 1
4
threadpool
size result: 1 || 1
4
threadpool
size result: 1 || 1
4
threadpool
size result: 1 || 1
4
threadpool
size result: 1 || 1
4
threadpool
size result: 1 || 1
4
threadpool
size result: 1 || 1
4
threadpool
size result: 1 || 1
4
threadpool
size result: 1 || 1
4
threadpool
size result: 1 || 1
4
threadpool
size result: 1 || 1
4
threadpool
size result: 1 || 1
4
threadpool
size result: 1 || 1
4
i believe that it has something to do with the nonblocking recv() call but i have been unsuccesful at finding the root of the problem, threadpool
threadpool
port:threadpool0
Listening on port: 5555
Thread: (accept_handler) start
Thread: (packet_handler) start
Connection RECV: 4
size result: 1 || 1
4
threadpool
size result: 1 || 1
4
threadpool
size result: 1 || 1
4
threadpool
size result: 1 || 1
4
threadpool
size result: 1 || 1
4
threadpool
size result: 1 || 1
4
threadpool
size result: 1 || 1
4
threadpool
size result: 1 || 1
4
threadpool
size result: 1 || 1
4
threadpool
size result: 1 || 1
4
threadpool
size result: 1 || 1
4
threadpool
size result: 1 || 1
4
threadpool
size result: 1 || 1
4
threadpool
size result: 1 || 1
4
threadpool
size result: 1 || 1
4
threadpool
size result: 1 || 1
4
threadpool
size result: 1 || 1
4
threadpool
size result: 1 || 1
4
threadpool
size result: 1 || 1
4
threadpool
size result: 1 || 1
4
threadpool
size result: 1 || 1
4
threadpool
size result: 1 || 1
4
threadpool
size result: 1 || 1
4
threadpool
size result: 1 || 1
4
threadpool
size result: 1 || 1
4
threadpool
size result: 1 || 1
4
threadpool
size result: 1 || 1
4
threadpool
size result: 1 || 1
4
threadpool
size result: 1 || 1
4
threadpool
size result: 1 || 1
4
 
    