У меня есть программа, названная timeout
, который делает это - записанный в C, первоначально в 1989, но обновляемый периодически с тех пор.
<час> Обновление: этому коду не удается скомпилировать на MacOS X, потому что SIGRTMIN не определяется и перестал работать к тайм-ауту при выполнении на MacOS X, потому что эти
signal()
функция там возобновляется wait()
после времен аварийного сигнала - который не является необходимым поведением. У меня есть новая версия timeout.c
, который имеет дело с обеими этими проблемами (использующий sigaction()
вместо signal()
). Как прежде, свяжитесь со мной для 10K gzipped файл tar с исходным кодом и страницей руководства (см. мой профиль). <час> /*
@(#)File: $RCSfile: timeout.c,v $
@(#)Version: $Revision: 4.6 $
@(#)Last changed: $Date: 2007/03/01 22:23:02 $
@(#)Purpose: Run command with timeout monitor
@(#)Author: J Leffler
@(#)Copyright: (C) JLSS 1989,1997,2003,2005-07
*/
#define _POSIX_SOURCE /* Enable kill() in <unistd.h> on Solaris 7 */
#define _XOPEN_SOURCE 500
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "stderr.h"
#define CHILD 0
#define FORKFAIL -1
static const char usestr[] = "[-vV] -t time [-s signal] cmd [arg ...]";
#ifndef lint
/* Prevent over-aggressive optimizers from eliminating ID string */
const char jlss_id_timeout_c[] = "@(#)$Id: timeout.c,v 4.6 2007/03/01 22:23:02 jleffler Exp $";
#endif /* lint */
static void catcher(int signum)
{
return;
}
int main(int argc, char **argv)
{
pid_t pid;
int tm_out;
int kill_signal;
pid_t corpse;
int status;
int opt;
int vflag = 0;
err_setarg0(argv[0]);
opterr = 0;
tm_out = 0;
kill_signal = SIGTERM;
while ((opt = getopt(argc, argv, "vVt:s:")) != -1)
{
switch(opt)
{
case 'V':
err_version("TIMEOUT", &"@(#)$Revision: 4.6 $ ($Date: 2007/03/01 22:23:02 $)"[4]);
break;
case 's':
kill_signal = atoi(optarg);
if (kill_signal <= 0 || kill_signal >= SIGRTMIN)
err_error("signal number must be between 1 and %d\n", SIGRTMIN - 1);
break;
case 't':
tm_out = atoi(optarg);
if (tm_out <= 0)
err_error("time must be greater than zero (%s)\n", optarg);
break;
case 'v':
vflag = 1;
break;
default:
err_usage(usestr);
break;
}
}
if (optind >= argc || tm_out == 0)
err_usage(usestr);
if ((pid = fork()) == FORKFAIL)
err_syserr("failed to fork\n");
else if (pid == CHILD)
{
execvp(argv[optind], &argv[optind]);
err_syserr("failed to exec command %s\n", argv[optind]);
}
/* Must be parent -- wait for child to die */
if (vflag)
err_remark("time %d, signal %d, child PID %u\n", tm_out, kill_signal, (unsigned)pid);
signal(SIGALRM, catcher);
alarm((unsigned int)tm_out);
while ((corpse = wait(&status)) != pid && errno != ECHILD)
{
if (errno == EINTR)
{
/* Timed out -- kill child */
if (vflag)
err_remark("timed out - send signal %d to process %d\n", (int)kill_signal, (int)pid);
if (kill(pid, kill_signal) != 0)
err_syserr("sending signal %d to PID %d - ", kill_signal, pid);
corpse = wait(&status);
break;
}
}
alarm(0);
if (vflag)
{
if (corpse == (pid_t) -1)
err_syserr("no valid PID from waiting - ");
else
err_remark("child PID %u status 0x%04X\n", (unsigned)corpse, (unsigned)status);
}
if (corpse != pid)
status = 2; /* Dunno what happened! */
else if (WIFEXITED(status))
status = WEXITSTATUS(status);
else if (WIFSIGNALED(status))
status = WTERMSIG(status);
else
status = 2; /* Dunno what happened! */
return(status);
}
, Если Вы хотите 'официальный' код для 'stderr.h' и 'stderr.c', свяжитесь со мной (см. мой профиль).
В C символы, начинающиеся с подчеркивания, за которым следует заглавная буква или другое подчеркивание, зарезервированы для реализации. Вы, как пользователь C, не должны создавать символы, которые начинаются с зарезервированных последовательностей. В C ++ ограничение более жесткое; вы, пользователь, не можете создавать символ, содержащий двойное подчеркивание.
Дано:
extern int ether_hostton (__const char *__hostname, struct ether_addr *__addr)
__THROW;
Нотация __ const
предназначена для учета возможности (что маловероятно) того, что компилятор использует этот код with поддерживает обозначения прототипов, но не имеет правильного понимания стандартного ключевого слова C89 const
. Макросы autoconf
могут по-прежнему проверять, есть ли у компилятора работающая поддержка const
; этот код можно использовать со сломанным компилятором, не имеющим такой поддержки.
Использование __ hostname
и __ addr
является мерой защиты для вас, пользователя заголовка. Если вы компилируете с GCC и параметром -Wshadow
, компилятор предупредит вас, когда какие-либо локальные переменные затеняют глобальную переменную. Если бы функция использовала только имя хоста
вместо __ имя хоста
, и если бы у вас была функция с именем имя хоста ()
, то было бы затенение. Использование имен, зарезервированных для реализации, исключает конфликт с вашим законным кодом.
Использование __ THROW
означает, что код при некоторых обстоятельствах может быть объявлен с какой-то «спецификацией выброса» . Это не стандартный C; это больше похоже на C ++.
необязательно объявляет или определяет идентификаторы, перечисленные в связанных будущих направлениях библиотеки
подпункт и идентификаторы, которые всегда зарезервированы либо для любого использования, либо для использования в качестве файла
идентификаторы области.
- Все идентификаторы, начинающиеся с подчеркивания и либо прописной буквы, либо другой подчеркивание всегда зарезервировано для любого использования.
- Все идентификаторы, начинающиеся с символа подчеркивания, всегда зарезервированы для использования в качестве идентификаторов с областью видимости файла как в обычном, так и в пространстве имен тегов.
- Каждое имя макроса в любом из следующих подпунктов (включая будущую библиотеку Направления) зарезервирован для использования, как указано, если включен какой-либо из связанных с ним заголовков; если явно не указано иное (см. 7.1.4).
- Все идентификаторы с внешней связью в любом из следующих подпунктов (включая будущие направления библиотеки) всегда зарезервированы для использования в качестве идентификаторов с внешними ссылка. 154)
- Каждый идентификатор с областью действия файла, перечисленной в любом из следующих подпунктов (включая будущие направления библиотеки) зарезервировано для использования в качестве имени макроса и идентификатора с область файла в том же пространстве имен, если включен какой-либо из связанных с ней заголовков.
Никакие другие идентификаторы не зарезервированы. Если программа объявляет или определяет идентификатор в контекст, в котором он зарезервирован (кроме разрешенного 7.1.4), или определяет зарезервированный идентификатор в качестве имени макроса, поведение не определено.
Если программа удаляет (с помощью #undef
) любое определение макроса идентификатора в первом
группы, указанной выше, поведение не определено.
Сноска 154) Список зарезервированных идентификаторов с внешней связью включает errno
, math_errhandling
,
setjmp
и va_end
.
См. Также Каковы правила использования символа подчеркивания в идентификаторе C ++ ; многие из тех же правил применимы как к C, так и к C ++, хотя встроенное правило двойного подчеркивания присутствует только в C ++, как упоминалось в верхней части этого ответа.
Имена с двойным нижним подчеркиванием зарезервированы для использования реализацией. Это не обязательно означает, что они внутренние сами по себе, хотя часто они таковы.
Идея в том, что вам не разрешается использовать имена, начинающиеся с __
, поэтому реализация может свободно использовать их в таких местах, как расширения макросов, или в именах расширений синтаксиса (например, __ gcnew
не является частью C ++, но Microsoft может добавить его в C ++ / CLI, будучи уверенным, что в существующем коде не должно быть чего-то вроде int __gcnew;
, что остановило бы компиляцию).
Чтобы узнать, что означают эти конкретные расширения, например __ const
, вам необходимо обратиться к документации для вашего конкретного компилятора / платформы. В данном конкретном случае
По соглашению в некоторых библиотеках это означает, что конкретный символ предназначен для внутреннего использования и не предназначен для того, чтобы быть частью общедоступного API библиотеки.
подчеркивание в __const означает, что это ключевое слово является расширением компилятора и его использование не является переносимым (ключевое слово const было добавлено в C в более поздней версии 89, я думаю). __THROW также является своего рода расширением, я предполагаю, что он определяется для некоторого __attribute __ (что-то), если используется gcc, но я не уверен в этом и слишком ленив, чтобы проверить. __Addr может означать все, что хотел программист, это просто имя.