C. Дочерний процесс. readline
Я пишу собственную shell. Вот main:
void signal_handler(int signo)
{
if (signo == SIGINT)
{
ft_putstr_fd("\n", 1);
rl_on_new_line();
rl_replace_line("", 1);
rl_redisplay();
}
}
int main(int argc, char **argv, char **envp)
{
(void) argc;
(void) argv;
char *line;
t_main main;
main.envp = array_2d_dup(envp);
main.exit_status = 0;
signal(SIGINT, signal_handler);
while (1)
{
line = readline("minishell -> ");
if (line == NULL)
exit(0);
if (*line == '\0')
continue ;
add_history(line);
if (parser(&line, &main) != -1)
{
execute(&main);
waitpid(*(main.pid), &main.exit_status, 0);
}
else
exit(1);
}
exit(1);
}
Функция парсер разбивает строку до нужного вида учитывая спец символы, она не интересна в данном вопросе.
Вот эта функция создает поток и запускает распарсенную команду из полученной строки:
void execute(t_main *main)
{
char *file_path;
char **command;
pid_t pid;
pid = fork();
if (pid != 0)
*(main->pid) = pid;
if (pid == 0)
{
command = parse_command(main->gap->arg, main->gap->comm);//подготовка к
file_path = parse_filename(main->gap->comm, main->envp);//передаче в execve()
main -> exit_status = EXIT_SUCCESS;
execve(file_path, command, main->envp);
perror(main->gap->comm);
main -> exit_status = EXIT_FAILURE;
exit(EXIT_FAILURE);
}
}
Что-то в коде может показаться лишним действием, но я удалил много функционала для сужения круга потенциальных ошибок. В итоге вот что происходит по нажатию ctr-c:
admin@Daniils-MacBook-Pro minishell % ./minishell
minishell -> ^C
minishell -> ^C
minishell -> ^C
minishell -> ^C
minishell ->
Но запустив команду cat и нажав ctr-c моя программа 2 раза печатает "Minishell -> ":
minishell -> ^C
minishell -> ^C
minishell -> ^C
minishell -> ^C
minishell -> cat
ekrmflker^C
minishell -> minishell ->
Я предполагаю, что это из-за использования процессов вместе с перехватом сигнала. У меня не получается это исправить, любая информация будет полезна. Спасибо!
Ответы (1 шт):
В итоге я сам нашел решение, вот так я изменил некоторые строки в execute():
pid = fork();
if (pid != 0)
signal(SIGINT, empty_signal_handler); //пустая функция
Не до конца понимаю почему это работает, но видимо при получении сигнала ctr-C родительский процесс выполнял обработчик и снова ждал завершение дочернего процесса. Соответственно в том случае если дочерний процесс это копия "minishell"(minishell -> ./minishell), то оба процесса выполняли обработчик и печатали "minishell -> ". Если дочерним процессом был, к примеру, "cat", то по ctr-C он завершался, а родитель выполнял и обработчик, и заходил на следующий виток цикла (while в main()), соответственно так же "minishell -> " печатался 2 раза. Еще раз оговорюсь, что я протестировал код множественными кейсами и он делает то что мне нужно, но не до конца понимаю почему это работает. Если вы зашли на эту страницу и знаете больше чем я, пожалуйста, напишите ответ. Описание функций из обработчика сигналов оставлю в комментариях.