C: прервать выполнение функции через n секунд (безопасно)

Модератор: Модераторы разделов

Ответить
Аватара пользователя
Stauffenberg
Сообщения: 2042
Статус: ☮ PEACE ☮
ОС: открытая и свободная

C: прервать выполнение функции через n секунд

Сообщение Stauffenberg »

Всем привет.

Искал ответ, но нашел решение только для отдельных процессов, выполнение которые можно оборвать при помощи сигнала. Мне же надо сделать тоже самое, но с обычной функцией.
Проходит n cекунд, и если функция все еще работает, то происходит автоматическое принудительное возвращение в вызывающую (например main) функцию. Я не уверен, что это вообще можно сделать...

Если кто сталкивался с такой задачей и знает как именно это можно реализовать, буду благодарен за любую информацию.
Labor omnia vincit

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.” (Brian Kernighan)
Спасибо сказали:
Аватара пользователя
Yaros
Сообщения: 501
ОС: Debian Wheezy / Gentoo

Re: C: прервать выполнение функции через n секунд

Сообщение Yaros »

Как я слышал, обходятся ассемблерными вставками, но не гарантирую верность информации.
=========
=Мой блог. =
=========
Gentoo-ниасилятар
Спасибо сказали:
Аватара пользователя
Stauffenberg
Сообщения: 2042
Статус: ☮ PEACE ☮
ОС: открытая и свободная

Re: C: прервать выполнение функции через n секунд

Сообщение Stauffenberg »

Тут, как я понимаю, нужен во-первых таймер. Само собой.
И во-вторых, все же как-то надо распараллелить процесс.
Labor omnia vincit

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.” (Brian Kernighan)
Спасибо сказали:
NickLion
Сообщения: 3408
Статус: аватар-невидимка
ОС: openSUSE Tumbleweed x86_64

Re: C: прервать выполнение функции через n секунд

Сообщение NickLion »

Какое доверие к прерываемому процессу? Первая простая схема: поток 1 запускает поток 2, ждёт n секунд, после чего устанавливает флаг и join к потоку 2; поток 2 выполняет работу, периодически проверяя флаг, если всё норм, то выходит раньше времени.
Спасибо сказали:
Аватара пользователя
Stauffenberg
Сообщения: 2042
Статус: ☮ PEACE ☮
ОС: открытая и свободная

Re: C: прервать выполнение функции через n секунд

Сообщение Stauffenberg »

NickLion писал(а):
20.11.2014 17:53
Какое доверие к прерываемому процессу?

Не процесс, а функция. Процесс прихлопнуть с помощью сигнала не проблема. Как реализовать "подобные отношения" в пределах одного потока/процесса?

NickLion писал(а):
20.11.2014 17:53
Первая простая схема: поток 1 запускает поток 2, ждёт n секунд, после чего устанавливает флаг и join к потоку 2; поток 2 выполняет работу, периодически проверяя флаг, если всё норм, то выходит раньше времени.

Поток или просто при помощи fork() это понятно. А как это сделать с обычной функцией? Что-то самое простое: main() вызывает f(), f() (в любом случае!) вызывает return через n секунд (либо сама main каким-то образом завершает f()).
Labor omnia vincit

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.” (Brian Kernighan)
Спасибо сказали:
Аватара пользователя
Bizdelnick
Модератор
Сообщения: 20791
Статус: nulla salus bello
ОС: Debian GNU/Linux

Re: C: прервать выполнение функции через n секунд

Сообщение Bizdelnick »

Stauffenberg писал(а):
20.11.2014 19:32
А как это сделать с обычной функцией?

Аргументом передавать ей таймаут, внутри в цикле проверять, не прошёл ли он. Разве это не очевидно?
Пишите правильно:
в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Спасибо сказали:
Аватара пользователя
Stauffenberg
Сообщения: 2042
Статус: ☮ PEACE ☮
ОС: открытая и свободная

Re: C: прервать выполнение функции через n секунд

Сообщение Stauffenberg »

Bizdelnick писал(а):
20.11.2014 19:35
Stauffenberg писал(а):
20.11.2014 19:32
А как это сделать с обычной функцией?

Аргументом передавать ей таймаут, внутри в цикле проверять, не прошёл ли он. Разве это не очевидно?

Вызываемая функция в свою очередь вызвает, к примеру, socket(), ответ от которого можно ждать... достаточно долго. Мне не нужен результат socket(), если ответ я жду более n секунд.

Куда Вы хотите поместить цикл, мне... да, не очевидно.
Labor omnia vincit

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.” (Brian Kernighan)
Спасибо сказали:
Аватара пользователя
Bizdelnick
Модератор
Сообщения: 20791
Статус: nulla salus bello
ОС: Debian GNU/Linux

Re: C: прервать выполнение функции через n секунд

Сообщение Bizdelnick »

socket() работает долго? С чего бы?
Вы, может быть, что-то вроде этого имеете в виду: https://stackoverflow.com/questions/4181784...ple-connections ?
Пишите правильно:
в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Спасибо сказали:
NickLion
Сообщения: 3408
Статус: аватар-невидимка
ОС: openSUSE Tumbleweed x86_64

Re: C: прервать выполнение функции через n секунд

Сообщение NickLion »

Я думал, что проблема в том, что сигналы работают на процесс, а не поток. Тогда да, как сказал Bizdelnick — просто параметр и проверка не достигнут ли таймаут. Вопрос доверия к коду функции остаётся, не должно быть блокирующих функций.
Спасибо сказали:
Аватара пользователя
Stauffenberg
Сообщения: 2042
Статус: ☮ PEACE ☮
ОС: открытая и свободная

Re: C: прервать выполнение функции через n секунд

Сообщение Stauffenberg »

NickLion писал(а):
20.11.2014 20:40
Вопрос доверия к коду функции остаётся, не должно быть блокирующих функций.

В идеале их конечно же не должно быть, но при работе с сетью всякое, знаете ли, случается. Характер ответов от каких-нибудь ESX постоянно меняется от версии к версии.

Bizdelnick писал(а):
20.11.2014 19:59
socket() работает долго? С чего бы?

Я написал "к примеру". Это может быть любая функция. Вам нужен пример функции, которая всегда запинается и подвешивает весь процесс?

Я хочу узнать как именно прервать функцию. У меня нет возможности после каждой операции в вызываемой функции проверять переданное значение таймаута, сравнивать его и, если оно именно то, что нужно, вызвать return.
Labor omnia vincit

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.” (Brian Kernighan)
Спасибо сказали:
Аватара пользователя
Bizdelnick
Модератор
Сообщения: 20791
Статус: nulla salus bello
ОС: Debian GNU/Linux

Re: C: прервать выполнение функции через n секунд

Сообщение Bizdelnick »

Stauffenberg писал(а):
21.11.2014 00:36
Я написал "к примеру". Это может быть любая функция. Вам нужен пример функции, которая всегда запинается и подвешивает весь процесс?

Не надо примеров. Давайте конкретную функцию, с которой возникла проблема. Для всего, что работает с сетью, должен быть предусмотрен таймаут, если Вы его не нашли, - значит плохо искали (ну или используете какую-то совсем уж непотребную библиотеку). Попробуем поискать вместе.

Stauffenberg писал(а):
21.11.2014 00:36
Я хочу узнать как именно прервать функцию.

"Прервать функцию" извне нельзя. Ну сами подумайте, если у Вас всего один поток, то кто эту функцию будет прерывать?

Stauffenberg писал(а):
21.11.2014 00:36
У меня нет возможности после каждой операции в вызываемой функции проверять переданное значение таймаута, сравнивать его и, если оно именно то, что нужно, вызвать return.

Возможность у Вас есть. Вероятно, нет желания. И, скорее всего, правильно, что нет.
Пишите правильно:
в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Спасибо сказали:
Аватара пользователя
Stauffenberg
Сообщения: 2042
Статус: ☮ PEACE ☮
ОС: открытая и свободная

Re: C: прервать выполнение функции через n секунд

Сообщение Stauffenberg »

Bizdelnick писал(а):
21.11.2014 01:01
Stauffenberg писал(а):
21.11.2014 00:36
Я хочу узнать как именно прервать функцию.

"Прервать функцию" извне нельзя. Ну сами подумайте, если у Вас всего один поток, то кто эту функцию будет прерывать?

Ну так поэтому я и написал:
Тут, как я понимаю, нужен во-первых таймер. Само собой.
И во-вторых, все же как-то надо распараллелить процесс.
Labor omnia vincit

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.” (Brian Kernighan)
Спасибо сказали:
Аватара пользователя
Stauffenberg
Сообщения: 2042
Статус: ☮ PEACE ☮
ОС: открытая и свободная

Re: C: прервать выполнение функции через n секунд

Сообщение Stauffenberg »

Bizdelnick писал(а):
21.11.2014 01:01
Stauffenberg писал(а):
21.11.2014 00:36
Я написал "к примеру". Это может быть любая функция. Вам нужен пример функции, которая всегда запинается и подвешивает весь процесс?

Не надо примеров. Давайте конкретную функцию, с которой возникла проблема. Для всего, что работает с сетью, должен быть предусмотрен таймаут, если Вы его не нашли, - значит плохо искали (ну или используете какую-то совсем уж непотребную библиотеку). Попробуем поискать вместе.

Спасибо конечно, поискать я и сам могу. Тратить чужое время ни к чему.
Как всегда и бывает, сложность проблемы в том, что накладываются несколько условий, и очень тяжело описать ВСЮ ситуацию целиком. Пытаешься разбить ее на части и спросить о том, что кажется наиболее вероятной причиной из тех, которые не понимаешь.
В моем конкретном случае я имею несколько параллеьных процессов, которые создают несколько разных соединений. Тут и icmp (raw-сокет), и я опрашиваю snmp (161/UDP), и еще создается несколько TCP-запросов, например, nsclient (12489/TCP). Все это работает вместе, и в данном случае очень сложно все это разбить на отдельные функции, потому что походу сканирования производится анализ для принятия решения о дальнейших действий и используются общие структуры для разных типов соединений.

Например, nsclient работает только на Windows, следовательно запрос на него надо делать только после того, как получили ответ от SNMP об используемой ОС, а SNMP конечно же UDP, так что мы должны использовать задержку... и мы вообще не можем узнать сразу получим ли мы ответ от SNMP или нет. Программа должна работать как можно быстрее, но еще важнее - чтобы ни в коем случае "опоздавший" ответ не был потерян и, как следствие, проигнорирован. Некоторые Cisco-рутеры, фаерволы, ESX, или какие-то другие сетевые устройства с гибридными функциями... запросы вообще фильтруют (не отбрасывают, когда ты можешь это увидеть, а фильтруют, так, что ты понятия не имеешь, что случилось с твоим пакетом. Это устройство включено? Оно есть в сети? Оно просто так настроено, что не отвечает?). И это еще не все... Это просто логика программы. Тут накладывается еще несколько проблем, связанных с окружением, в котором все это будет работать, которые тоже стоит учитывать и следоательно - тут описывать.

Обо всем этом нет смысла тут спрашивать, да и учился я не для того, чтобы проблемы с помощью форума решать. Я разбиваю задачу на подзадачи, проблему на подпроблемы. Что-то могу отбросить сразу, что-то запрограммировать иначе, что-то найти в интернете, что-то - спросить на этом форуме, а что-то - в специальной рассылке по сетям. Но в этом случае вопрос получается очень абстрактный, потому что это лишь десятая часть проблемы, на которую со всех сторон давят те или иные условия. Дебажа эту проблему, мне легче всего "отрезать" то, что сразу понятно, что сломано. Тут и так процесс на процессе, поток на потоке, поэтому еще глубже уходить в это слишком муторно. Мне просто пришла в голову идея гасить функции, если что-то в ней пошло не так. Я никогда этого не делал. Как только остальная часть программы будет работать как надо, я вернусь и перепрограммирую проблемные участки кода.

Так о чем это я? Да, я просто хотел сказать, что в проблеме разберусь сам, а вот узнать как возвращаться из "зомби-функции" принудительно, было бы прикольно :)
Labor omnia vincit

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.” (Brian Kernighan)
Спасибо сказали:
Аватара пользователя
Bizdelnick
Модератор
Сообщения: 20791
Статус: nulla salus bello
ОС: Debian GNU/Linux

Re: C: прервать выполнение функции через n секунд

Сообщение Bizdelnick »

В сторону использования неблокирующего режима не смотрели?
Пишите правильно:
в консоли
вку́пе (с чем-либо)
в общем
вообще
в течение (часа)
новичок
нюанс
по умолчанию
приемлемо
проблема
пробовать
трафик
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current
Контактная информация:

Re: C: прервать выполнение функции через n секунд

Сообщение drBatty »

Stauffenberg писал(а):
20.11.2014 15:54
Искал ответ, но нашел решение только для отдельных процессов, выполнение которые можно оборвать при помощи сигнала. Мне же надо сделать тоже самое, но с обычной функцией.

NoWay
Stauffenberg писал(а):
20.11.2014 19:32
А как это сделать с обычной функцией?

делить на ноль нельзя. Вам обязательно нужен другой процесс, для отслеживания вашей функции.
Bizdelnick писал(а):
20.11.2014 19:35
Аргументом передавать ей таймаут, внутри в цикле проверять, не прошёл ли он. Разве это не очевидно?

это не прерывание. Это просто функция, которая помимо всего прочего считает время, и завершается, если время вышло.
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
NickLion
Сообщения: 3408
Статус: аватар-невидимка
ОС: openSUSE Tumbleweed x86_64

Re: C: прервать выполнение функции через n секунд

Сообщение NickLion »

Stauffenberg
Учтите, нельзя прервать что-то "хорошо". Такое "хорошее" прерывание можно сделать внитри самого кода: проверкой функции, setjmp/longjmp, исключения. Но извне (процесс или поток — не важно) всегда можно попасть в плохое место, это нормально для Вас?
Спасибо сказали:
Аватара пользователя
Stauffenberg
Сообщения: 2042
Статус: ☮ PEACE ☮
ОС: открытая и свободная

Re: C: прервать выполнение функции через n секунд

Сообщение Stauffenberg »

Ладно, всем спасибо. Буду дальше разбираться.
Еще раз спасибо за ответы.

NickLion писал(а):
21.11.2014 10:42
Stauffenberg
Учтите, нельзя прервать что-то "хорошо". Такое "хорошее" прерывание можно сделать внитри самого кода: проверкой функции, setjmp/longjmp, исключения. Но извне (процесс или поток — не важно) всегда можно попасть в плохое место, это нормально для Вас?

Вот именно поэтому в описании к теме написано "безопасно" (:
Но сейчас меня интересует возможность прерывания в принципе.

Bizdelnick писал(а):
21.11.2014 02:11
В сторону использования неблокирующего режима не смотрели?

Естественно с этого все начиналось
Labor omnia vincit

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.” (Brian Kernighan)
Спасибо сказали:
NickLion
Сообщения: 3408
Статус: аватар-невидимка
ОС: openSUSE Tumbleweed x86_64

Re: C: прервать выполнение функции через n секунд

Сообщение NickLion »

Прервать в принципе — pthread_cancel, pthread_kill.
Спасибо сказали:
Аватара пользователя
Stauffenberg
Сообщения: 2042
Статус: ☮ PEACE ☮
ОС: открытая и свободная

Re: C: прервать выполнение функции через n секунд

Сообщение Stauffenberg »

drBatty писал(а):
21.11.2014 02:16
Stauffenberg писал(а):
20.11.2014 19:32
А как это сделать с обычной функцией?

делить на ноль нельзя. Вам обязательно нужен другой процесс, для отслеживания вашей функции.


К примеру, connect() легко прерывается после n секунд вот так:

Код: Выделить всё

void alarm_hndlr (int sig)
{
return;
}

int main()
{
...
signal(SIGALRM, alarm_hndlr);
alarm(5);
rc = connect (s, (struct sockaddr *)&peer, sizeof(peer));
alarm(0);
if (rc < 0)
{
if (error == EINTR)
error(1, 0, "halli hallo\n");
...

}


Есть еще select(), исключающих блокировку, но накладывающий ряд своих проблем.
Labor omnia vincit

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.” (Brian Kernighan)
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current
Контактная информация:

Re: C: прервать выполнение функции через n секунд

Сообщение drBatty »

Stauffenberg писал(а):
21.11.2014 15:46
К примеру, connect() легко прерывается

оно там внутри где-то форкается. Для этой функции прерывание — штатная фича.

Есть и код ошибки для этого случая:

Код: Выделить всё

       EINTR  The system call was interrupted by a signal that was caught; see signal(7).
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Ответить