LINUX.ORG.RU

Убиение потока


0

0

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

int main() { create_thread(); while(1) { if (flag) { destroy_thread(); create_thread(); } }

}

Делаю это потому , что в потоке создается слушающий сокет , и его нужно закрыть и по новой открыть. В функции destroy_thread() вызывается pthread_join c 2-мя параметрами , первый - id-шник потока , второй - NULL, и вроде как все работает. Так вот будет ли работать такая схема? Дело в том , что я не вижу , что поток джойнится, т.е. не могу проконтролировать это доступными средствами :-)

Офигительное форматирование - никак не могу привыкнуть :

int main()
{
     create_thread();
  
     while(1)
     {
       if (flag)
       {
         destroy_thread();
         create_thread(); 
       }
     }

}

iivvaann
() автор топика
Ответ на: комментарий от andreyu

Поясню мысль :-)
Тред создаю так :

pthread_create(&id, NULL, &thread_main, (void *) i);

Функция потока :

void * thread_main(void *arg)
{
    int             connfd;
    void            web_child(int);
    socklen_t       clilen;
    struct sockaddr *cliaddr;

    cliaddr = Malloc(addrlen);

    printf("thread %d starting  listenfd=%d\n", (int) arg,listenfd1);
    for ( ; ; ) 
    {
        clilen = addrlen;
        connfd = Accept(listenfd1, cliaddr, &clilen);

        .................

        Close(connfd);
    }

    printf("thread %d end .... \n", (int) arg);

}

Так вот при джойне дело до последнего принта не доходит .
Неважно , что если вместо принта поставить сислог - все равно не работает ...


iivvaann
() автор топика

>while(1) { if (flag){ ... } }
руки оторвать! (за попадание на первую строчку top-а)

в чем проблема закрыть сокет оттуда, где у тебя присваивается значение flag=1 ??

xydo ★★
()
Ответ на: комментарий от xydo

>> руки оторвать! (за попадание на первую строчку top-а)

ну это же псевдо-код

>> в чем проблема закрыть сокет оттуда, где у тебя присваивается значение flag=1 ?

проблема в том , что хочется пере-открыть ПОТОК , а не сокет ...

iivvaann
() автор топика
Ответ на: комментарий от iivvaann

>Так вот при джойне дело до последнего принта не доходит .
какой кошмар!! этож где это виданно, чтобы даже бесконечный цикл не завершался??

(сарказм понятен?)

xydo ★★
()
Ответ на: комментарий от xydo

>> какой кошмар!! этож где это виданно, чтобы даже бесконечный цикл не завершался??

я почему-то считал , что при джойне функция потока должна вернуться , так сказать

iivvaann
() автор топика
Ответ на: комментарий от iivvaann

>я почему-то считал , что при джойне функция потока должна вернуться , так сказать
unreachable code не выполняется никогда!

xydo ★★
()
Ответ на: комментарий от iivvaann

если поток "зависнет" на accept, то никакой join не поможет, ты просто будешь висеть в джойне до тех пор, пока поток не сдохнет. кури доки, так ты не сможешь ничего сделать... делай чтение сокета ассинхронным в потоке, и переодически проверяй твой flag в этом потоке, если он стал 1, то надо закрыть все сокеты, и умереть, иначе никак.

Cy6erBr4in ★★★
()
Ответ на: комментарий от Cy6erBr4in

кстати по идее в posix thread есть механизм "отмены" (Cancellation) потоков, но, насколько я понял, это достаточно опасная функция, так как выделенная память внутри потока за пределами стека никак не контролируется

chicane
()
Ответ на: комментарий от chicane

а на сколько я понял этот канцелейшен, то есть просто стандартная возможность не городить своих "flag", а выставлять стандартными средствами некий флаг, извне потока, а в самом потоке так же проверять его... по сути то же самое что и глобальная переменная flag, только уникальная для каждого потока, хоть и имеют они одинаковое имя...

Cy6erBr4in ★★★
()
Ответ на: комментарий от Cy6erBr4in

А вообще I don't care at all... я на Erlang пишу, у меня нет таких проблем :)

Cy6erBr4in ★★★
()
Ответ на: комментарий от Cy6erBr4in

насколько я помню, оно реально отменяет поток, но могу и ошибаться. Во всяком случае помню, что в posix threads такая возможность была, и помню, как мне в каком то канале в irc не рекомендовали этим пользоваться...

chicane
()
Ответ на: комментарий от chicane

> не рекомендовали этим пользоваться

Я тоже сталкивался с отрицательными рекомендациями на этот счет.

В GLib все просто: там нет вообще g_thread_cancel() :)

В Qt есть terminate, но рекомендуют не пользоваться.

gag ★★★★★
()
Ответ на: комментарий от gag

щас еще раз прочитал про "cancellation" - насколько я понял, там определены некоторые точки "отмены" потока - это основные стандартные функции, в каждой точке поток проверяет свой флаг остановки и останавливается если нужно. А опасно это тем, что остановившись так в произвольном месте, он случайно не осовбодит мьютекс или другой объект синхронизации, или не освободить выделенную память и это почти невозможно проконтролировать...

chicane
()
Ответ на: комментарий от chicane

в более высокоуровневых языках, можно решить аналогичным образом проблему, но генерируя исключение в потоке, и потом его отлавливая...

chicane
()
Ответ на: комментарий от chicane

> в более высокоуровневых языках, можно решить аналогичным образом проблему, но генерируя исключение в потоке, и потом его отлавливая...

Интересно, такого еще не встречал. А можно подробней?

gag ★★★★★
()
Ответ на: комментарий от gag

>Интересно, такого еще не встречал. А можно подробней?

ну например вот тут http://stackoverflow.com/questions/323972/is-there-any-way-to-kill-a-thread-i... есть пример как сделать такой тред, сам не проверял, поэтому хз как оно работает на практике.

Также можно сделать что то наподобии этого http://mail.python.org/pipermail/python-list/2004-May/260937.html тут через sys.settrace устанавливается trace и если флаг остановки установлен генерируется исключение SystemExit, которое можно отловить в контексте нити. Но там же автор признается, что если кто то другой установит аналогичный trace (IDE к примеру) его реализация не будет работать.

chicane
()
Ответ на: комментарий от chicane

но это кстати тоже не спасет в некоторых случаях.

ну например если мы используем сторонний модуль, а внутри его реализации где то затался такой код:

lock.acquire() instruction_1 ... instruction_n lock.release()

без всяких with, тогда если сгенерировать исключение после instruction_1 мы не отпустим lock --> deadlock

chicane
()

Имхо, самый чистый метод - мультиплексирование ввода-вывода.
Т.е. поток будет ждать не одно событие (появление коннекта), а несколько. В вашем случае - два.
Самый простой (известный мне) способ сделать изменение флага I/O-событием, это создать сокет, через который будут взаимодействовать потоки.

solid
()
Ответ на: комментарий от chicane

> без всяких with, тогда если сгенерировать исключение после instruction_1 мы не отпустим lock --> deadlock

В смысле выше сказанного, что в контексте потока мы смогли бы это сделать, но у нас нет исходных текстов модуля и мы просто не знаем какие ресурсы освобождать?

Короче, каждый поток должен сам заботиться о своих поминках, и поэтому получать указание к завершению, а не незамедлительное принуждение.

gag ★★★★★
()
Ответ на: комментарий от gag

>В смысле выше сказанного, что в контексте потока мы смогли бы это сделать, но у нас нет исходных текстов модуля и мы просто не знаем какие ресурсы освобождать?

смысл в том, чт оесли модуль писали не мы, то мы не можем быть 100% увереным, что сгенерировав исключение в произвольном месте всё будет нормально при дальнейшей работе

chicane
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.