一旦超过时间限制就终止进程
Killing a process once time limit exceeded
我已经研究了以下代码很长一段时间,但无法真正弄明白。
任务是读取终端命令并每 x 秒 运行 它;如果命令在等待时间内没有完成,我们想终止进程,然后 运行 再次执行命令。
任何帮助将非常感激。
我很确定我没有正确使用 waitpid();我将如何使用 waitpid 来实现目标?
此外,我将如何检测子进程中的错误?计划是在子进程发生错误时终止父进程。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>
#include <signal.h>
#include <sys/wait.h>
/*
*
*/
int main(int argc, char** argv) {
int waitingTime;
if (argc < 3) {
printf("Invalid number of arguments provided. Please specify a command and exactly one parameter.");
return (EXIT_FAILURE);
}
// -n parameter specified? If so, set the waiting time.
if (argc == 5 && strcmp(argv[3], "-n") == 0) {
waitingTime = atoi(argv[4]);
} else {
waitingTime = 5; // Default waiting time.
}
char* cmd = (char*)malloc(sizeof(argv[1]));
cmd = argv[1];
char* param = (char*)malloc(sizeof(argv[2]));
param = argv[2];
// Print the read command and its param
printf("Command: %s, Parameter: %s, Interval: %d\n\n", cmd, param, waitingTime);
pid_t pid;
for (;;) {
// Declared here for scope
int secsWaited;
secsWaited = 0;
pid = fork();
if (pid == 0) {
pid = getpid();
printf("==============\n");
execlp(cmd, cmd, param, "/", (char *)NULL);
printf("Excec failed; killing the proccess.");
kill(pid, SIGKILL);
} else if (pid > 0) {
int status, code;
for (;;) {
code = waitpid(pid, &status, WNOHANG);
if (code == 0 && secsWaited >= waitingTime) {
kill(pid, SIGKILL);
printf("Child stopped");
break;
} else if (code == 0 && secsWaited < waitingTime) {
secsWaited++;
sleep(1);
} else {
break;
}
}
/*if (!WIFEXITED(status)) {
printf("Time exceeding, stopping child.");
// Get parent process id and kill it.
kill(getpid(), SIGKILL);
}*/
// Sleep for the specified time
sleep(waitingTime - secsWaited);
} else {
return (EXIT_FAILURE);
}
}
free(cmd);
free(param);
return (EXIT_SUCCESS);
}
您的逻辑有点太复杂了(例如,太多不同的 sleep
调用和 if/else
梯形图逻辑)。
此外,不需要 malloc
argv
字符串——它们可以直接使用。
我对其进行了简化并进行了一些重组以使其正常工作[请原谅不必要的样式清理]:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>
#include <signal.h>
#include <sys/wait.h>
/*
*
*/
int
main(int argc, char **argv)
{
int waitingTime;
if (argc < 3) {
printf("Invalid number of arguments provided. Please specify a command and exactly one parameter.");
return (EXIT_FAILURE);
}
// -n parameter specified? If so, set the waiting time.
if (argc == 5 && strcmp(argv[3], "-n") == 0) {
waitingTime = atoi(argv[4]);
}
else {
waitingTime = 5; // Default waiting time.
}
char *cmd = argv[1];
char *param = argv[2];
// Print the read command and its param
printf("Command: %s, Parameter: %s, Interval: %d\n\n",
cmd, param, waitingTime);
pid_t pid;
int code = -1;
int status;
int killflg = 1;
for (;;) {
// Declared here for scope
int secsWaited;
secsWaited = 0;
pid = fork();
// stop on fork failure
if (pid < 0) {
killflg = 1;
break;
}
// child process
if (pid == 0) {
pid = getpid();
printf("==============\n");
#if 0
execlp(cmd, cmd, param, "/", (char *) NULL);
#else
execlp(cmd, cmd, param, (char *) NULL);
#endif
printf("Excec failed; killing the proccess.");
// NOTE/BUG: this is the child so pid is zero, so killing it is wrong
#if 0
kill(pid, SIGKILL);
#else
exit(1);
#endif
}
killflg = 0;
for (;;) {
code = waitpid(pid, &status, WNOHANG);
if (code > 0)
break;
if (killflg)
continue;
secsWaited++;
sleep(1);
if (secsWaited >= waitingTime) {
printf("timeout\n");
kill(pid, SIGKILL);
killflg = 1;
}
}
if (! killflg)
break;
}
#if 0
free(cmd);
free(param);
#endif
if (killflg)
code = EXIT_FAILURE;
else
code = EXIT_SUCCESS;
return code;
}
更新:
Right now, the program will stop after one iteration; if I remove the breakpoint at if (! killflg)
, it will work as expected. Am I missing something or is this just a misunderstanding?
你是对的——我的错。我在你的问题中遗漏了以下内容:
The task is to read a terminal command and to run it every x seconds;
将break
改为sleep(waitingTime - secsWaited)
。
但是,一种更可靠的跟踪经过时间的方法可能是通过两次调用 time(2)
:
在 killflg = 0
之后,执行:time_t todbeg = time(NULL); time_t todelap;
。然后,您可以 [anywhere] 使用以下方法获取经过的时间:todelap = time(NULL) - todbeg;
[这里,todelap
类似于 secsWaited
]。这可能比递增 secsWaited
.
更好
time
只有秒分辨率。要获得更精确的控制,请考虑使用 clock_gettime
[具有纳秒分辨率]。
这是一个我经常使用的计算经过时间的函数 [在 小数 秒内]:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>
#include <signal.h>
#include <sys/wait.h>
#include <time.h>
double
tvgetf(void)
{
struct timespec ts;
double sec;
clock_gettime(CLOCK_REALTIME,&ts);
sec = ts.tv_nsec;
sec /= 1e9;
sec += ts.tv_sec;
return sec;
}
/*
*
*/
int
main(int argc, char **argv)
{
int waitingTime;
if (argc < 3) {
printf("Invalid number of arguments provided. Please specify a command and exactly one parameter.");
return (EXIT_FAILURE);
}
// -n parameter specified? If so, set the waiting time.
if (argc == 5 && strcmp(argv[3], "-n") == 0) {
waitingTime = atoi(argv[4]);
}
else {
waitingTime = 5; // Default waiting time.
}
char *cmd = argv[1];
char *param = argv[2];
// Print the read command and its param
printf("Command: %s, Parameter: %s, Interval: %d\n\n", cmd, param, waitingTime);
pid_t pid;
int code = -1;
int status;
int killflg = 1;
double todzero = tvgetf();
for (;;) {
// Declared here for scope
double todbeg = tvgetf();
double todelap;
pid = fork();
// stop on fork failure
if (pid < 0) {
killflg = 1;
break;
}
// child process
if (pid == 0) {
pid = getpid();
printf("============== (%.9f)\n",tvgetf() - todzero);
execlp(cmd, cmd, param, (char *) NULL);
printf("Excec failed; killing the proccess.");
exit(1);
}
killflg = 0;
for (;;) {
code = waitpid(pid, &status, WNOHANG);
if (code > 0)
break;
if (killflg)
continue;
usleep(1000);
todelap = tvgetf() - todbeg;
if (todelap >= waitingTime) {
printf("timeout\n");
kill(pid, SIGKILL);
killflg = 1;
}
}
// do _not_ wait -- we already timed out
if (killflg)
continue;
// get final elapsed time for this round and the amount of time
// remaining until the next interval
todelap = tvgetf() - todbeg;
useconds_t time_to_wait = ((double) waitingTime - todelap) * 1e6;
// wait until the next time period
if (time_to_wait > 0)
usleep(time_to_wait);
}
if (killflg)
code = EXIT_FAILURE;
else
code = EXIT_SUCCESS;
return code;
}
旁注: 我在这里使用了 usleep
,但是,虽然稍微复杂一些,但认为使用 nanosleep
更好
我已经研究了以下代码很长一段时间,但无法真正弄明白。 任务是读取终端命令并每 x 秒 运行 它;如果命令在等待时间内没有完成,我们想终止进程,然后 运行 再次执行命令。 任何帮助将非常感激。 我很确定我没有正确使用 waitpid();我将如何使用 waitpid 来实现目标?
此外,我将如何检测子进程中的错误?计划是在子进程发生错误时终止父进程。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>
#include <signal.h>
#include <sys/wait.h>
/*
*
*/
int main(int argc, char** argv) {
int waitingTime;
if (argc < 3) {
printf("Invalid number of arguments provided. Please specify a command and exactly one parameter.");
return (EXIT_FAILURE);
}
// -n parameter specified? If so, set the waiting time.
if (argc == 5 && strcmp(argv[3], "-n") == 0) {
waitingTime = atoi(argv[4]);
} else {
waitingTime = 5; // Default waiting time.
}
char* cmd = (char*)malloc(sizeof(argv[1]));
cmd = argv[1];
char* param = (char*)malloc(sizeof(argv[2]));
param = argv[2];
// Print the read command and its param
printf("Command: %s, Parameter: %s, Interval: %d\n\n", cmd, param, waitingTime);
pid_t pid;
for (;;) {
// Declared here for scope
int secsWaited;
secsWaited = 0;
pid = fork();
if (pid == 0) {
pid = getpid();
printf("==============\n");
execlp(cmd, cmd, param, "/", (char *)NULL);
printf("Excec failed; killing the proccess.");
kill(pid, SIGKILL);
} else if (pid > 0) {
int status, code;
for (;;) {
code = waitpid(pid, &status, WNOHANG);
if (code == 0 && secsWaited >= waitingTime) {
kill(pid, SIGKILL);
printf("Child stopped");
break;
} else if (code == 0 && secsWaited < waitingTime) {
secsWaited++;
sleep(1);
} else {
break;
}
}
/*if (!WIFEXITED(status)) {
printf("Time exceeding, stopping child.");
// Get parent process id and kill it.
kill(getpid(), SIGKILL);
}*/
// Sleep for the specified time
sleep(waitingTime - secsWaited);
} else {
return (EXIT_FAILURE);
}
}
free(cmd);
free(param);
return (EXIT_SUCCESS);
}
您的逻辑有点太复杂了(例如,太多不同的 sleep
调用和 if/else
梯形图逻辑)。
此外,不需要 malloc
argv
字符串——它们可以直接使用。
我对其进行了简化并进行了一些重组以使其正常工作[请原谅不必要的样式清理]:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>
#include <signal.h>
#include <sys/wait.h>
/*
*
*/
int
main(int argc, char **argv)
{
int waitingTime;
if (argc < 3) {
printf("Invalid number of arguments provided. Please specify a command and exactly one parameter.");
return (EXIT_FAILURE);
}
// -n parameter specified? If so, set the waiting time.
if (argc == 5 && strcmp(argv[3], "-n") == 0) {
waitingTime = atoi(argv[4]);
}
else {
waitingTime = 5; // Default waiting time.
}
char *cmd = argv[1];
char *param = argv[2];
// Print the read command and its param
printf("Command: %s, Parameter: %s, Interval: %d\n\n",
cmd, param, waitingTime);
pid_t pid;
int code = -1;
int status;
int killflg = 1;
for (;;) {
// Declared here for scope
int secsWaited;
secsWaited = 0;
pid = fork();
// stop on fork failure
if (pid < 0) {
killflg = 1;
break;
}
// child process
if (pid == 0) {
pid = getpid();
printf("==============\n");
#if 0
execlp(cmd, cmd, param, "/", (char *) NULL);
#else
execlp(cmd, cmd, param, (char *) NULL);
#endif
printf("Excec failed; killing the proccess.");
// NOTE/BUG: this is the child so pid is zero, so killing it is wrong
#if 0
kill(pid, SIGKILL);
#else
exit(1);
#endif
}
killflg = 0;
for (;;) {
code = waitpid(pid, &status, WNOHANG);
if (code > 0)
break;
if (killflg)
continue;
secsWaited++;
sleep(1);
if (secsWaited >= waitingTime) {
printf("timeout\n");
kill(pid, SIGKILL);
killflg = 1;
}
}
if (! killflg)
break;
}
#if 0
free(cmd);
free(param);
#endif
if (killflg)
code = EXIT_FAILURE;
else
code = EXIT_SUCCESS;
return code;
}
更新:
Right now, the program will stop after one iteration; if I remove the breakpoint at
if (! killflg)
, it will work as expected. Am I missing something or is this just a misunderstanding?
你是对的——我的错。我在你的问题中遗漏了以下内容:
The task is to read a terminal command and to run it every x seconds;
将break
改为sleep(waitingTime - secsWaited)
。
但是,一种更可靠的跟踪经过时间的方法可能是通过两次调用 time(2)
:
在 killflg = 0
之后,执行:time_t todbeg = time(NULL); time_t todelap;
。然后,您可以 [anywhere] 使用以下方法获取经过的时间:todelap = time(NULL) - todbeg;
[这里,todelap
类似于 secsWaited
]。这可能比递增 secsWaited
.
time
只有秒分辨率。要获得更精确的控制,请考虑使用 clock_gettime
[具有纳秒分辨率]。
这是一个我经常使用的计算经过时间的函数 [在 小数 秒内]:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>
#include <signal.h>
#include <sys/wait.h>
#include <time.h>
double
tvgetf(void)
{
struct timespec ts;
double sec;
clock_gettime(CLOCK_REALTIME,&ts);
sec = ts.tv_nsec;
sec /= 1e9;
sec += ts.tv_sec;
return sec;
}
/*
*
*/
int
main(int argc, char **argv)
{
int waitingTime;
if (argc < 3) {
printf("Invalid number of arguments provided. Please specify a command and exactly one parameter.");
return (EXIT_FAILURE);
}
// -n parameter specified? If so, set the waiting time.
if (argc == 5 && strcmp(argv[3], "-n") == 0) {
waitingTime = atoi(argv[4]);
}
else {
waitingTime = 5; // Default waiting time.
}
char *cmd = argv[1];
char *param = argv[2];
// Print the read command and its param
printf("Command: %s, Parameter: %s, Interval: %d\n\n", cmd, param, waitingTime);
pid_t pid;
int code = -1;
int status;
int killflg = 1;
double todzero = tvgetf();
for (;;) {
// Declared here for scope
double todbeg = tvgetf();
double todelap;
pid = fork();
// stop on fork failure
if (pid < 0) {
killflg = 1;
break;
}
// child process
if (pid == 0) {
pid = getpid();
printf("============== (%.9f)\n",tvgetf() - todzero);
execlp(cmd, cmd, param, (char *) NULL);
printf("Excec failed; killing the proccess.");
exit(1);
}
killflg = 0;
for (;;) {
code = waitpid(pid, &status, WNOHANG);
if (code > 0)
break;
if (killflg)
continue;
usleep(1000);
todelap = tvgetf() - todbeg;
if (todelap >= waitingTime) {
printf("timeout\n");
kill(pid, SIGKILL);
killflg = 1;
}
}
// do _not_ wait -- we already timed out
if (killflg)
continue;
// get final elapsed time for this round and the amount of time
// remaining until the next interval
todelap = tvgetf() - todbeg;
useconds_t time_to_wait = ((double) waitingTime - todelap) * 1e6;
// wait until the next time period
if (time_to_wait > 0)
usleep(time_to_wait);
}
if (killflg)
code = EXIT_FAILURE;
else
code = EXIT_SUCCESS;
return code;
}
旁注: 我在这里使用了 usleep
,但是,虽然稍微复杂一些,但认为使用 nanosleep