_exec_script() close fd and reset signal
+ somes more adjustements in _exec_script() + rough notes for non blocking CGI
This commit is contained in:
@@ -72,16 +72,24 @@ std::string Webserv::_exec_cgi(Client *client)
|
||||
char* env_cstr[19] = {NULL};
|
||||
std::vector<std::string> env_vector;
|
||||
env_vector.reserve(18);
|
||||
int i = 0;
|
||||
|
||||
_set_env_vector(client, env_vector);
|
||||
_set_env_cstr(env_cstr, env_vector);
|
||||
script_output = _exec_script(client, env_cstr);
|
||||
|
||||
int i = 0;
|
||||
while (env_cstr[i] != NULL)
|
||||
delete[] env_cstr[i++];
|
||||
try {
|
||||
_set_env_cstr(env_cstr, env_vector);
|
||||
script_output = _exec_script(client, env_cstr);
|
||||
|
||||
return script_output;
|
||||
while (env_cstr[i] != NULL)
|
||||
delete[] env_cstr[i++];
|
||||
|
||||
return script_output;
|
||||
}
|
||||
catch (const Webserv::ExecFail& e)
|
||||
{
|
||||
while (env_cstr[i] != NULL)
|
||||
delete[] env_cstr[i++];
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
std::string Webserv::_dup_env(std::string var, std::string val = "")
|
||||
@@ -166,6 +174,8 @@ void Webserv::_set_env_cstr(char *env_cstr[], std::vector<std::string> &env_vect
|
||||
env_cstr[18] = NULL;
|
||||
} */
|
||||
|
||||
#define STATUS_500 std::string("Status: 500" CRLF CRLF);
|
||||
|
||||
std::string Webserv::_exec_script(Client *client, char *env[])
|
||||
{
|
||||
#define RD 0
|
||||
@@ -190,21 +200,43 @@ std::string Webserv::_exec_script(Client *client, char *env[])
|
||||
|
||||
pid = fork();
|
||||
if (pid == -1)
|
||||
std::cerr << "fork crashed" << std::endl;
|
||||
perror("err fork()");
|
||||
else if (pid == 0) // child
|
||||
{
|
||||
// _close_all_clients();
|
||||
close(FD_WR_TO_CHLD);
|
||||
close(FD_RD_FR_CHLD);
|
||||
dup2(FD_RD_FR_PRNT, STDIN_FILENO);
|
||||
dup2(FD_WR_TO_PRNT, STDOUT_FILENO);
|
||||
path = "." + client->get_rq_script_path();
|
||||
std::signal(SIGPIPE, SIG_DFL);
|
||||
std::signal(SIGINT, SIG_DFL);
|
||||
|
||||
_close_all_clients_fd();
|
||||
::close(_epfd);
|
||||
::close(FD_WR_TO_CHLD);
|
||||
::close(FD_RD_FR_CHLD);
|
||||
if (dup2(FD_RD_FR_PRNT, STDIN_FILENO) == -1)
|
||||
{
|
||||
perror("err dup2()");
|
||||
::close(FD_RD_FR_PRNT); // Valgind debug, not essential
|
||||
::close(FD_WR_TO_PRNT); // Valgind debug, not essential
|
||||
throw ExecFail();
|
||||
}
|
||||
if (dup2(FD_WR_TO_PRNT, STDOUT_FILENO) == -1)
|
||||
{
|
||||
perror("err dup2()");
|
||||
::close(FD_RD_FR_PRNT); // Valgind debug, not essential
|
||||
::close(FD_WR_TO_PRNT); // Valgind debug, not essential
|
||||
throw ExecFail();
|
||||
}
|
||||
|
||||
::close(FD_RD_FR_PRNT);
|
||||
::close(FD_WR_TO_PRNT);
|
||||
|
||||
path = "." + client->get_rq_script_path(); // Wut ? Only relative path ?
|
||||
/*DEBUG*/std::cerr << "execve:[" << path << "]\n";
|
||||
execve(path.c_str(), nll, env);
|
||||
// for tests execve crash :
|
||||
//execve("wrong", nll, env);
|
||||
std::cerr << "execve crashed.\n";
|
||||
// TODO HUGO : check errno
|
||||
if (execve(path.c_str(), nll, env) == -1) // replace path for debug error forcing
|
||||
{
|
||||
perror("err execve()");
|
||||
::close(STDIN_FILENO); // Valgind debug, not essential
|
||||
::close(STDOUT_FILENO); // Valgind debug, not essential
|
||||
throw ExecFail();
|
||||
}
|
||||
}
|
||||
else //parent
|
||||
{
|
||||
@@ -213,17 +245,30 @@ std::string Webserv::_exec_script(Client *client, char *env[])
|
||||
write(FD_WR_TO_CHLD, body.c_str(), body.size());
|
||||
close(FD_WR_TO_CHLD);
|
||||
waitpid(-1, NULL, 0);
|
||||
// We could maybe,
|
||||
// add FD_RD_FR_CHLD to epoll,
|
||||
// return to the main loop,
|
||||
// read FD_RD_FR_CHLD each time epoll say its ready,
|
||||
// then try waitpid() with WNOHANG after each read.
|
||||
// when waitpid() tell us its finish (or maybe when epoll return EPOLLHUP)
|
||||
// then actually parse the script_output and send it to the client.
|
||||
|
||||
memset(buf, '\0', CGI_BUF_SIZE);
|
||||
while (read(FD_RD_FR_CHLD, buf, CGI_BUF_SIZE - 1) > 0)
|
||||
ssize_t ret = 1;
|
||||
while (ret > 0)
|
||||
{
|
||||
script_output += buf;
|
||||
memset(buf, '\0', CGI_BUF_SIZE);
|
||||
ret = read(FD_RD_FR_CHLD, buf, CGI_BUF_SIZE);
|
||||
if (ret == -1)
|
||||
{
|
||||
std::perror("err recv()");
|
||||
script_output = STATUS_500;
|
||||
break;
|
||||
}
|
||||
script_output.append(buf, ret);
|
||||
}
|
||||
close(FD_RD_FR_CHLD);
|
||||
}
|
||||
if (script_output.empty())
|
||||
script_output = "Status: 500" CRLF CRLF;
|
||||
script_output = STATUS_500;
|
||||
|
||||
return script_output;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user