diff --git a/memo.txt b/memo.txt index 5d901c0..dd8e42a 100644 --- a/memo.txt +++ b/memo.txt @@ -23,6 +23,9 @@ For non blocking CGI : - check status in autoindex +- merge changes from hugo5 to master (attention a pas casse svp :clown:) + + ----Priorité modérée------------------------ - namespace utils ? - change "std::string" to reference "std::string &" in most functions @@ -47,3 +50,12 @@ and add "const" if apropriate. - change "std::string" to reference "std::string &" in most functions and add "const" if apropriate. - Il faut vérifier le path de la requête, voir si le serveur est bien censé délivrer cette ressource et si le client y a accès, avant d'appeler le CGI. + +Valgrind error RESOLVED ! : +==847174== 1,314 bytes in 1 blocks are definitely lost in loss record 1 of 1 +==847174== at 0x483BE63: operator new(unsigned long) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so) +==847174== by 0x49AA35D: std::__cxx11::basic_string, std::allocator >::_M_mutate(unsigned long, unsigned long, char const*, unsigned long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28) +==847174== by 0x49ABB52: std::__cxx11::basic_string, std::allocator >::_M_append(char const*, unsigned long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28) +==847174== by 0x426BC5: Webserv::_read_cgi_output(cgi_pipe_rfd&) (run_loop.cpp:39) // (LUKE: its an string.append() call) +==847174== by 0x427962: Webserv::run() (run_loop.cpp:153) +==847174== by 0x4052E9: main (main.cpp:38) diff --git a/srcs/Client.cpp b/srcs/Client.cpp index e7be9f6..60ebc9a 100644 --- a/srcs/Client.cpp +++ b/srcs/Client.cpp @@ -13,6 +13,7 @@ Client::Client() assigned_server(NULL), assigned_location(NULL), cgi_pipe_rfd(0), + cgi_pid(0), _fd(0), _port(""), _ip(""), @@ -29,6 +30,7 @@ Client::Client(int afd, listen_socket *lsocket, std::string aport, std::string a assigned_server(NULL), assigned_location(NULL), cgi_pipe_rfd(0), + cgi_pid(0), _fd(afd), _port(aport), _ip(aip), @@ -240,6 +242,7 @@ void Client::clear() assigned_server = NULL; assigned_location = NULL; cgi_pipe_rfd = 0; + cgi_pid = 0; cgi_output.clear(); } diff --git a/srcs/Client.hpp b/srcs/Client.hpp index a99c020..2d6e879 100644 --- a/srcs/Client.hpp +++ b/srcs/Client.hpp @@ -59,6 +59,7 @@ class Client ServerConfig *assigned_server; // cant be const cause of error_pages.operator[] const LocationConfig *assigned_location; int cgi_pipe_rfd; + pid_t cgi_pid; std::string cgi_output; // getters diff --git a/srcs/cgi-bin/cgi_cpp.cpp b/srcs/cgi-bin/cgi_cpp.cpp index e35824b..36845cc 100644 --- a/srcs/cgi-bin/cgi_cpp.cpp +++ b/srcs/cgi-bin/cgi_cpp.cpp @@ -1,6 +1,7 @@ # include "cgi_utils.hpp" # include +# include int main (int ac, char **av, char ** env) { @@ -10,11 +11,19 @@ int main (int ac, char **av, char ** env) (void)ac; (void)av; - ::sleep(30); + // ::sleep(5); fill_response_basic(env, http_body, http_header); - std::cout << http_header << CRLF CRLF << http_body; + std::cout << http_header; + std::flush(std::cout); + ::sleep(2); + std::cout << CRLF CRLF; + std::flush(std::cout); + ::sleep(2); + std::cout << http_body; + std::flush(std::cout); + ::sleep(2); return 0; } diff --git a/srcs/webserv/Webserv.hpp b/srcs/webserv/Webserv.hpp index d15b8c5..1b8ce8e 100644 --- a/srcs/webserv/Webserv.hpp +++ b/srcs/webserv/Webserv.hpp @@ -44,15 +44,6 @@ void signal_handler(int signum); # define MIME_TYPE_DEFAULT "application/octet-stream" -struct cgi_pipe_rfd -{ - int fd; - pid_t cgi_pid; - Client *client; -}; -bool operator==(const cgi_pipe_rfd& lhs, int fd); -bool operator==(int fd, const cgi_pipe_rfd& rhs); - class Webserv { public: @@ -74,7 +65,6 @@ class Webserv private: int _epfd; std::vector _listen_sockets; - std::vector _cgi_pipe_rfds; std::vector _servers; std::vector _clients; std::map _http_status; @@ -147,9 +137,10 @@ class Webserv - void _read_cgi_output(cgi_pipe_rfd &cgi_fd); - void _handle_epoll_error_cgi_fd(uint32_t events, std::vector::iterator it); - void _cgi_epollhup(uint32_t events, std::vector::iterator it); + Client *_find_cgi_fd(int cgi_fd); + void _read_cgi_output(Client *client); + void _handle_epoll_error_cgi_fd(uint32_t events, Client *client); + void _cgi_epollhup(uint32_t events, Client *client); diff --git a/srcs/webserv/cgi.cpp b/srcs/webserv/cgi.cpp index 16b7fc1..af77b75 100644 --- a/srcs/webserv/cgi.cpp +++ b/srcs/webserv/cgi.cpp @@ -223,16 +223,21 @@ void Webserv::_exec_script(Client *client, char *env[]) _epoll_update(client->get_cl_fd(), 0, EPOLL_CTL_DEL); client->cgi_pipe_rfd = FD_RD_FR_CHLD; - struct cgi_pipe_rfd new_cgi_fd; - new_cgi_fd.fd = FD_RD_FR_CHLD; - new_cgi_fd.cgi_pid = pid; - new_cgi_fd.client = client; - _cgi_pipe_rfds.push_back(new_cgi_fd); + client->cgi_pid = pid; } } +#define STATUS_500 std::string("Status: 500" CRLF CRLF); + void Webserv::_check_script_output(Client *client, std::string & output) { + size_t pos; + pos = client->cgi_output.find(CRLF CRLF); + if (pos == 0 || pos == NPOS) + { + client->status = 500;; + return; + } _check_script_status(client, output); if (client->status >= 400 && client->status < 600) return; diff --git a/srcs/webserv/close.cpp b/srcs/webserv/close.cpp index f9bbea3..145287c 100644 --- a/srcs/webserv/close.cpp +++ b/srcs/webserv/close.cpp @@ -40,39 +40,6 @@ void Webserv::_close_all_clients_fd() } } -// TODO : not sure for zombie cgi-proccess, need to verif -void Webserv::_close_cgi_pipe_rfd(int fd) -{ - std::vector::iterator it = _cgi_pipe_rfds.begin(); - std::vector::iterator it_end = _cgi_pipe_rfds.end(); - while (it != it_end) - { - if (*it == fd) - { - std::cerr << "close cgi-fd " << fd << "\n"; - if (::close(fd) == -1) - std::perror("err close()"); - _cgi_pipe_rfds.erase(it); - break; - } - ++it; - } -} - -void Webserv::_close_all_cgi_pipe_rfd() -{ - std::vector::iterator it = _cgi_pipe_rfds.begin(); - std::vector::iterator it_end = _cgi_pipe_rfds.end(); - while (it != it_end) - { - std::cerr << "close cgi-fd " << it->fd << "\n"; - if (::close(it->fd) == -1) - std::perror("err close()"); - ++it; - } - _cgi_pipe_rfds.clear(); -} - void Webserv::_close_all_listen_sockets() { // TODO : change like clients (clear in place of pop_back) while (!_listen_sockets.empty()) diff --git a/srcs/webserv/response.cpp b/srcs/webserv/response.cpp index dc80171..e278988 100644 --- a/srcs/webserv/response.cpp +++ b/srcs/webserv/response.cpp @@ -50,7 +50,7 @@ int Webserv::_send_response(Client *client) return SEND_IN_PROGRESS; } } - else if (client->cgi_pipe_rfd) + else if (!client->cgi_output.empty()) { // /*DEBUG*/ std::cout << "\n" B_PURPLE "[response]:" RESET "\n"; ::print_special(client->response); std::cout << B_PURPLE "-----------" RESET "\n\n"; // /*DEBUG*/ std::cout << "\n" B_PURPLE "[script output]:" RESET "\n"; ::print_special(script_output); std::cout << B_PURPLE "-----------" RESET "\n\n"; diff --git a/srcs/webserv/run_loop.cpp b/srcs/webserv/run_loop.cpp index b63b3f7..6301c6e 100644 --- a/srcs/webserv/run_loop.cpp +++ b/srcs/webserv/run_loop.cpp @@ -4,104 +4,94 @@ #define MAX_EVENTS 42 // arbitrary #define TIMEOUT 3000 -// TODO: temp to move in own file -bool operator==(const cgi_pipe_rfd& lhs, int fd) - { return lhs.fd == fd; } - -bool operator==(int fd, const cgi_pipe_rfd& rhs) - { return fd == rhs.fd; } #define BUFSIZE 8192 // (8Ko) #define STATUS_500 std::string("Status: 500" CRLF CRLF); -void Webserv::_read_cgi_output(cgi_pipe_rfd &cgi_fd) +void Webserv::_read_cgi_output(Client *client) { char buf[BUFSIZE]; ssize_t ret; pid_t wait_ret; std::cerr << "_read_cgi_output()" << "\n"; - std::cerr << "cgi_pid = " << cgi_fd.cgi_pid << "\n"; - std::cerr << "client fd = " << cgi_fd.client->get_cl_fd() << "\n"; - std::cerr << "cgi fd = " << cgi_fd.fd << "\n"; + std::cerr << "cgi_pid = " << client->cgi_pid << "\n"; + std::cerr << "client fd = " << client->get_cl_fd() << "\n"; + std::cerr << "cgi fd = " << client->cgi_pipe_rfd << "\n"; - ret = ::read(cgi_fd.fd, buf, BUFSIZE); + ret = ::read(client->cgi_pipe_rfd, buf, BUFSIZE); std::cerr << "cgi read ret = " << ret << "\n"; if (ret == -1) { std::perror("err read(cgi_fd)"); - cgi_fd.client->cgi_output = STATUS_500; + client->cgi_output = STATUS_500; } else if (ret == 0) - { - std::cerr << "cgi read 0 :o" << "\n"; - } + std::cerr << "Madame s'il vous plait, du Ketchup pour mon hamburger" << " (AKA:ret=0)" << "\n"; else - { - cgi_fd.client->cgi_output.append(buf, ret); - } - - - wait_ret = ::waitpid(cgi_fd.cgi_pid, NULL, WNOHANG); - std::cerr << "cgi waitpid ret = " << wait_ret << "\n"; - if (wait_ret == 0 && ret == -1) - { - _epoll_update(cgi_fd.client->get_cl_fd(), EPOLLOUT, EPOLL_CTL_ADD); - _close_cgi_pipe_rfd(cgi_fd.fd); - // TODO: kill the child :) - } - else if (wait_ret == cgi_fd.cgi_pid) - { - _epoll_update(cgi_fd.client->get_cl_fd(), EPOLLOUT, EPOLL_CTL_ADD); - _close_cgi_pipe_rfd(cgi_fd.fd); - } - return; + client->cgi_output.append(buf, ret); } -void Webserv::_handle_epoll_error_cgi_fd(uint32_t events, std::vector::iterator it) +void Webserv::_handle_epoll_error_cgi_fd(uint32_t events, Client *client) { (void)events; std::cerr << "cgi EPOLLERR" << "\n"; - std::cerr << "cgi_pid = " << it->cgi_pid << "\n"; - std::cerr << "client fd = " << it->client->get_cl_fd() << "\n"; - std::cerr << "cgi fd = " << it->fd << "\n"; + std::cerr << "cgi_pid = " << client->cgi_pid << "\n"; + std::cerr << "client fd = " << client->get_cl_fd() << "\n"; + std::cerr << "cgi fd = " << client->cgi_pipe_rfd << "\n"; pid_t wait_ret; - wait_ret = ::waitpid(it->cgi_pid, NULL, WNOHANG); + wait_ret = ::waitpid(client->cgi_pid, NULL, WNOHANG); std::cerr << "cgi EPOLLHUP waitpid ret = " << wait_ret << "\n"; if (wait_ret == 0) { - _epoll_update(it->client->get_cl_fd(), EPOLLOUT, EPOLL_CTL_ADD); - _close_cgi_pipe_rfd(it->fd); + _epoll_update(client->get_cl_fd(), EPOLLOUT, EPOLL_CTL_ADD); + if (::close(client->cgi_pipe_rfd) == -1) + std::perror("err close()"); // TODO: kill the child :) } - else if (wait_ret == it->cgi_pid) + else if (wait_ret == client->cgi_pid) { - _epoll_update(it->client->get_cl_fd(), EPOLLOUT, EPOLL_CTL_ADD); - _close_cgi_pipe_rfd(it->fd); + _epoll_update(client->get_cl_fd(), EPOLLOUT, EPOLL_CTL_ADD); + if (::close(client->cgi_pipe_rfd) == -1) + std::perror("err close()"); } } -void Webserv::_cgi_epollhup(uint32_t events, std::vector::iterator it) +void Webserv::_cgi_epollhup(uint32_t events, Client *client) { (void)events; + (void)client; + std::cerr << "cgi EPOLLHUP" << "\n"; - std::cerr << "cgi_pid = " << it->cgi_pid << "\n"; - std::cerr << "client fd = " << it->client->get_cl_fd() << "\n"; - std::cerr << "cgi fd = " << it->fd << "\n"; + std::cerr << "cgi_pid = " << client->cgi_pid << "\n"; + std::cerr << "client fd = " << client->get_cl_fd() << "\n"; + std::cerr << "cgi fd = " << client->cgi_pipe_rfd << "\n"; + if (client->cgi_pipe_rfd) + { + if (::close(client->cgi_pipe_rfd) == -1) + std::perror("err close()"); + } + client->cgi_pipe_rfd = 0; pid_t wait_ret; - wait_ret = ::waitpid(it->cgi_pid, NULL, WNOHANG); + wait_ret = ::waitpid(client->cgi_pid, NULL, WNOHANG); std::cerr << "cgi EPOLLHUP waitpid ret = " << wait_ret << "\n"; - if (wait_ret == 0) + if (wait_ret == client->cgi_pid) { - _epoll_update(it->client->get_cl_fd(), EPOLLOUT, EPOLL_CTL_ADD); - _close_cgi_pipe_rfd(it->fd); - // TODO: kill the child :) + _epoll_update(client->get_cl_fd(), EPOLLOUT, EPOLL_CTL_ADD); } - else if (wait_ret == it->cgi_pid) +} + +Client *Webserv::_find_cgi_fd(int cgi_fd) +{ + std::vector::iterator it = _clients.begin(); + std::vector::iterator it_end = _clients.end(); + while (it != it_end) { - _epoll_update(it->client->get_cl_fd(), EPOLLOUT, EPOLL_CTL_ADD); - _close_cgi_pipe_rfd(it->fd); - } + if (it->cgi_pipe_rfd == cgi_fd) + return (&(*it)); + ++it; + } + return (NULL); } void Webserv::run() @@ -112,7 +102,7 @@ void Webserv::run() int i; int count_loop = 0; std::vector::iterator it_lsocket; - std::vector::iterator it_cgi_fd; + Client *client_cgi = NULL; g_run = true; while (g_run) @@ -135,7 +125,7 @@ void Webserv::run() { try { it_lsocket = std::find(_listen_sockets.begin(), _listen_sockets.end(), events[i].data.fd); - it_cgi_fd = std::find(_cgi_pipe_rfds.begin(), _cgi_pipe_rfds.end(), events[i].data.fd); // Could be moved in the loop to avoid useless find() call + client_cgi = _find_cgi_fd(events[i].data.fd); if (it_lsocket != _listen_sockets.end()) { if (events[i].events & EPOLLERR || events[i].events & EPOLLHUP) @@ -143,14 +133,14 @@ void Webserv::run() else if (events[i].events & EPOLLIN) _accept_connection(*it_lsocket); } - else if (it_cgi_fd != _cgi_pipe_rfds.end()) + else if (client_cgi) { if (events[i].events & EPOLLERR) - _handle_epoll_error_cgi_fd(events[i].events, it_cgi_fd); - else if (events[i].events & EPOLLHUP) - _cgi_epollhup(events[i].events, it_cgi_fd); + _handle_epoll_error_cgi_fd(events[i].events, client_cgi); else if (events[i].events & EPOLLIN) - _read_cgi_output(*it_cgi_fd); + _read_cgi_output(client_cgi); + else if ( (events[i].events & EPOLLHUP) && !(events[i].events & EPOLLIN) ) + _cgi_epollhup(events[i].events, client_cgi); } else {