英文:
Why pipes not working for cat | cat | ls?
问题
以下是代码部分的翻译:
void executing_commands(t_minish *data)
{
t_cmd *cmd;
int process_status;
process_status = 0;
cmd = data->cmds;
if (!cmd->full_cmd)
return ;
creating_pipes(data);
while (cmd && cmd->full_cmd)
cmd = creating_child(&cmd, data);
closing_all_fd(data);
cmd = data->cmds;
while (cmd)
{
waitpid(data->child, &process_status, 0);
if (data->cmds && !check_parent_builtin(&cmd))
g_status = WEXITSTATUS(process_status);
cmd = cmd->next;
}
}
t_cmd *creating_child(t_cmd **cmd, t_minish *data)
{
int pid;
if (check_parent_builtin(cmd))
executing_builtin(data, cmd);
else
{
pid = fork();
if (ft_memcmp((*cmd)->full_cmd[0], "minishell", 10))
set_signals(EXEC);
data->child = pid;
if (pid == -1)
{
closing_all_fd(data);
error_manager(2, data, NULL);
}
else if (pid == 0)
child_process(data, cmd);
}
return (*cmd)->next;
}
void child_process(t_minish *data, t_cmd **cmd)
{
switching_input_output(data, cmd);
closing_all_fd(data);
if (check_child_builtin(cmd))
executing_builtin(data, cmd);
else
launching_command(data, cmd);
}
void switching_input_output(t_minish *data, t_cmd **cmd)
{
if ((*cmd)->output > 1)
{
if (dup2((*cmd)->output, STDOUT_FILENO) < 0)
error_manager(6, data, cmd);
close((*cmd)->output);
}
if ((*cmd)->input)
{
if (dup2((*cmd)->input, STDIN_FILENO) < 0)
error_manager(6, data, cmd);
close((*cmd)->input);
}
if ((*cmd)->file_in)
{
if (dup2((*cmd)->file_in, STDIN_FILENO) < 0)
error_manager(6, data, cmd);
close((*cmd)->file_in);
}
if ((*cmd)->file_out)
{
if (dup2((*cmd)->file_out, STDOUT_FILENO) < 0)
error_manager(6, data, cmd);
close((*cmd)->file_out);
}
}
void launching_command(t_minish *data, t_cmd **cmd)
{
if (execve((*cmd)->full_path, (*cmd)->full_cmd, data->env_table) == -1)
error_manager(3, data, cmd);
}
void closing_all_fd(t_minish *data)
{
t_cmd *cmd;
cmd = data->cmds;
while (cmd)
{
if (cmd->input)
close(cmd->input);
if (cmd->output > 1)
close(cmd->output);
cmd = cmd->next;
}
}
void closing_fd_if_redirections(t_minish *data)
{
t_cmd *cmd;
cmd = data->cmds;
while (cmd)
{
if (cmd->file_in && cmd->input)
close(cmd->input);
cmd = cmd->next;
}
}
void creating_pipes(t_minish *data)
{
int fd[2];
t_cmd *cmd;
cmd = data->cmds;
while (cmd->next != NULL)
{
if (pipe(fd) == -1)
error_manager(1, data, NULL);
cmd->output = fd[1];
cmd->next->input = fd[0];
if (!cmd->next->next)
cmd->next->last = 1;
cmd = cmd->next;
}
closing_fd_if_redirections(data);
}
如果您需要更多帮助或有其他问题,请随时提出。
英文:
I really need help and any suggestions will be very welcomed. Me and a mate have coded a mini version of the Shell and I did parsing and executing parts. All is working properly except for some cases that probably are hiding some logic that I can't catch and I'm actually stuck. In particular when launching cat | cat | ls
cmd the ls
output is ok but the cat
behavior is not what expected. Instead of waiting for the stdin (not having any argument) the prompt is suddenly returned. That probably means that there's an issue with pipes not closing at the right place, but I'm not able to find where exactly. Here below you will find the executing part. If anyone please could help with kindness and a noncompetitive attitude will be very appreciated. Here is the github repo for any further details GitHub Repo
void executing_commands(t_minish *data)
{
t_cmd *cmd;
int process_status;
process_status = 0;
cmd = data->cmds;
if (!cmd->full_cmd)
return ;
creating_pipes(data);
while (cmd && cmd->full_cmd)
cmd = creating_child(&cmd, data);
closing_all_fd(data);
cmd = data->cmds;
while (cmd)
{
waitpid(data->child, &process_status, 0);
if (data->cmds && !check_parent_builtin(&cmd))
g_status = WEXITSTATUS(process_status);
cmd = cmd->next;
}
}
t_cmd *creating_child(t_cmd **cmd, t_minish *data)
{
int pid;
if (check_parent_builtin(cmd))
executing_builtin(data, cmd);
else
{
pid = fork();
if (ft_memcmp((*cmd)->full_cmd[0], "minishell", 10))
set_signals(EXEC);
data->child = pid;
if (pid == -1)
{
closing_all_fd(data);
error_manager(2, data, NULL);
}
else if (pid == 0)
child_process(data, cmd);
}
return ((*cmd)->next);
}
void child_process(t_minish *data, t_cmd **cmd)
{
switching_input_output(data, cmd);
closing_all_fd(data);
if (check_child_builtin(cmd))
executing_builtin(data, cmd);
else
launching_command(data, cmd);
}
void switching_input_output(t_minish *data, t_cmd **cmd)
{
if ((*cmd)->output > 1)
{
if (dup2((*cmd)->output, STDOUT_FILENO) < 0)
error_manager(6, data, cmd);
close((*cmd)->output);
}
if ((*cmd)->input)
{
if (dup2((*cmd)->input, STDIN_FILENO) < 0)
error_manager(6, data, cmd);
close((*cmd)->input);
}
if ((*cmd)->file_in)
{
if (dup2((*cmd)->file_in, STDIN_FILENO) < 0)
error_manager(6, data, cmd);
close((*cmd)->file_in);
}
if ((*cmd)->file_out)
{
if (dup2((*cmd)->file_out, STDOUT_FILENO) < 0)
error_manager(6, data, cmd);
close((*cmd)->file_out);
}
}
void launching_command(t_minish *data, t_cmd **cmd)
{
if (execve((*cmd)->full_path, (*cmd)->full_cmd, data->env_table) == -1)
error_manager(3, data, cmd);
}
void closing_all_fd(t_minish *data)
{
t_cmd *cmd;
cmd = data->cmds;
while (cmd)
{
if (cmd->input)
close(cmd->input);
if (cmd->output > 1)
close(cmd->output);
cmd = cmd->next;
}
}
void closing_fd_if_redirections(t_minish *data)
{
t_cmd *cmd;
cmd = data->cmds;
while (cmd)
{
if (cmd->file_in && cmd->input)
close(cmd->input);
cmd = cmd->next;
}
}
void creating_pipes(t_minish *data)
{
int fd[2];
t_cmd *cmd;
cmd = data->cmds;
while (cmd->next != NULL)
{
if (pipe(fd) == -1)
error_manager(1, data, NULL);
cmd->output = fd[1];
cmd->next->input = fd[0];
if (!cmd->next->next)
cmd->next->last = 1;
cmd = cmd->next;
}
closing_fd_if_redirections(data);
}
I tried not to create all the pipes needed all in a sudden in order to better control closing in parent and child processes with just a pipe for each loop but still not working
答案1
得分: 1
>…提示突然返回。这可能意味着管道没有在正确位置关闭的问题…
你的概率估计出错了。错误在于shell不等待管道中所有的命令,因为尽管你在executing_commands
函数中的while (cmd)
循环中正确地尝试等待每个命令,但整个管道只有一个存储位置data->child
,所以子进程PID会被后续的命令覆盖,最终shell只能等待最后一个命令。
当然,解决方法是将child
按照cmd
而不是data
存储。
英文:
>… the prompt is suddenly returned. That probably means that there's an issue with pipes not closing at the right place …
Your probability estimation went wrong. The error is that the shell does not wait for all the commands in the pipeline, because, though you rightly try to wait for each command in the while (cmd)
loop in executing_commands
, there is only one storage location data->child
for the whole pipeline, so a child PID is overwritten by the following, and at the end the shell can only wait for the last command.
Of course the remedy is to store child
per cmd
rather than per data
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论