gpt4 book ai didi

c - execve 失败 - 忽略退出语句

转载 作者:行者123 更新时间:2023-11-30 16:32:04 26 4
gpt4 key购买 nike

我在混合时遇到一个奇怪的问题fgetsexecve一起。

我有一个函数可以从文件中读取行并执行它们,方法是通过它自己的函数解析它们,或者使用execve 。为了简单起见,我的测试文件只有外部函数:

echo whoowhee
lx
ls
dir

第二个命令,lx不存在,所以此时 execve应该会失败。

这是我从文件中读取的代码:

  while(fgets(line, 1024, testfile) != NULL){
if(strlen(line) < 3){continue;}
if(line[0] == '#'){continue;}

printf("%s%s", value("PROMPT"), line); // Emulates the prompt

//Terminates line at right place to simulate input
line[strlen(line)-2] = '\0';

execute(line);

Var *prompt = retrieveVar("PROMPT");
sprintf(prompt->value, "< Executing script... - [%s] > $ ", value("EXITCODE"));

lineNo++;
}

这是我的 fork-exec block :

  if(pid == 0){ // Child

// For loop for using all paths
for(int i = 0; i < pathn; i++){
args[0] = paths[i];

// Executes command path[i] with arguments args with environment envp
execve(paths[i], args, envp);
}

perror("execve");
exit(0);
}
else if(pid > 0){ //Parent
current_pid = pid;

if(setpgid(pid, pid) != 0) perror("setpid");

// Waits if background flag not activated.
if(BG == 0){
// WUNTRACED used to stop waiting when suspended
waitpid(current_pid, &status, WUNTRACED);

if(WIFEXITED(status)){
setExitcode(WEXITSTATUS(status));
}
else if(WIFSIGNALED(status)){
printf("Process received SIGNAL %d\n", WTERMSIG(status));
}
}
}
else{
perror("fork()");
}

execve需要程序的绝对路径,paths是程序应该存在的可能路径的数组。 BG指明进程是否应在后台执行,value("EXITCODE")是进程的退出代码,execute您猜对了,就是执行该行的函数。

现在,这是我运行测试文件时的输出,代码如下:

<Welcome to Eggshell> $ echo whoowhee
whoowhee
< Executing script... - [0] > $ lx
execve: No such file or directory
< Executing script... - [0] > $ ls
add-on codecov.yml documentation eggshell.c LICENSE Makefile README.md switch.sh val.log
ci createfile.txt eggshell eggshell.h main.c Makefile-Clang src testinput.txt
< Executing script... - [0] > $ dir
add-on codecov.yml documentation eggshell.c LICENSE Makefile README.md switch.sh val.log
ci createfile.txt eggshell eggshell.h main.c Makefile-Clang src testinput.txt
< Executing script... - [0] > $ dir
add-on codecov.yml documentation eggshell.c LICENSE Makefile README.md switch.sh val.log
ci createfile.txt eggshell eggshell.h main.c Makefile-Clang src testinput.txt

如您所见,dir运行两次。

如果我向文本文件添加另一个无意义的命令,问题还不止于此:

echo whoowhee
lx
onetimesoneistwo
ls
dir

如果我尝试运行该函数,它最终会陷入无限循环。不仅如此,这一次它还会一遍又一遍地运行整个文件!

但是,如果我删除 exit来自fork-exec位,然后重新运行该函数,结果如下:

<Welcome to Eggshell> $ echo whoowhee
whoowhee
< Executing script... - [0] > $ lx
execve: No such file or directory
< Executing script... - [0] > $ onetimesoneistwo
execve: No such file or directory
< Executing script... - [0] > $ ls
add-on codecov.yml documentation eggshell.c LICENSE Makefile README.md switch.sh val.log
ci createfile.txt eggshell eggshell.h main.c Makefile-Clang src testinput.txt
< Executing script... - [0] > $ dir
add-on codecov.yml documentation eggshell.c LICENSE Makefile README.md switch.sh val.log
ci createfile.txt eggshell eggshell.h main.c Makefile-Clang src testinput.txt
< Executing script... - [0] > $ ls
add-on codecov.yml documentation eggshell.c LICENSE Makefile README.md switch.sh val.log
ci createfile.txt eggshell eggshell.h main.c Makefile-Clang src testinput.txt
< Executing script... - [0] > $ dir
add-on codecov.yml documentation eggshell.c LICENSE Makefile README.md switch.sh val.log
ci createfile.txt eggshell eggshell.h main.c Makefile-Clang src testinput.txt
< Executing script... - [0] > $ onetimesoneistwo
execve: No such file or directory
< Executing script... - [0] > $ ls
add-on codecov.yml documentation eggshell.c LICENSE Makefile README.md switch.sh val.log
ci createfile.txt eggshell eggshell.h main.c Makefile-Clang src testinput.txt
< Executing script... - [0] > $ dir
add-on codecov.yml documentation eggshell.c LICENSE Makefile README.md switch.sh val.log
ci createfile.txt eggshell eggshell.h main.c Makefile-Clang src testinput.txt
< Executing script... - [0] > $ ls
add-on codecov.yml documentation eggshell.c LICENSE Makefile README.md switch.sh val.log
ci createfile.txt eggshell eggshell.h main.c Makefile-Clang src testinput.txt
< Executing script... - [0] > $ dir
add-on codecov.yml documentation eggshell.c LICENSE Makefile README.md switch.sh val.log
ci createfile.txt eggshell eggshell.h main.c Makefile-Clang src testinput.txt

令人惊讶的是,这不是无限循环!确保 onetimesoneistwo 之后的每个命令运行 4 次,并且 onetimesoneistwo它本身运行了两次,但至少它是有意义的。

我猜想 execve失败会导致 fork 的子进程永远不会终止,但是为什么会 exit导致无限循环,而没有 exit之后复制所有指令?

有趣的是,如果我正常运行程序,自己提供输入而不是从文件中获取输入,则不会发生同样的事情,所以我的猜测是我的源函数或我的源函数出现了严重错误。 fork-exec 代码。

最佳答案

至少对我来说,解决方案似乎是使用 _exit 而不是 exit。如果 execve 失败,使用前者会立即杀死子进程,而不是产生奇怪的无限循环效果。

尽管我仍然不知道为什么 exit 会导致无限循环,以及为什么 _exit 可以工作,而 exit 却不能...

更新:效果不太好。解决这个问题的方法是在当前循环之前使用 fgets ,并将所有行存储在字符串数组缓冲区中。然后,在下一个循环中,我只需从数组中逐行读取行。由于 exit 正在重置文件指针,因此解决方案是不再在循环内使用文件指针。

关于c - execve 失败 - 忽略退出语句,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50308216/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com