LINUX.ORG.RU

как запускать потры при старте?

 


0

3

Допустим есть gen_server, который при старте запускает порт, написаный на С. handle_call обычно шлёт порту запрос и ждёт ответ. Когда приходит ответ - отвечает клиенту.

Порт написан таким образом, что при запуске делает read(0, ... и ждёт команд.

Я обратил внимание, что если убивать ерланговский сервер, то read() в порте возврящает ноль. Я сделал так, что порт при этом тоже останавливается, предполагая, что дескриптор закрыли с другой стороны.

Проблема в том, что если сервер запускать через параметры командной строки при старте (erl -run), то read() в порте возврящает ноль ещё при старте и порт завершает работу.

Это баг или фича? Я правильно понимаю, что в вм чего-то там не успевает проинициализироваться? Как с этим бороться? Версия вм r13b03, как в последней не знаю, пока не обновлял. Исходники вм пока не смотрел.

Спасибо.

cast r а то он вроде ерлангист, а на тег не подписан.

Да, ещё обратил внимание, что это не всегда так. В некоторых случает работает как и ожидалось. Никаких нулей в порт не приходит.

★★★★

Последнее исправление: nanoolinux (всего исправлений: 1)

Если причина в том, что внутри ВМ что-то тупо не успевает проинициализироваться, то можно делать отложеную инициализацию (пример).

Можешь выложить пример для воспроизведения?

Алсо erlang@c.j.r

ymn ★★★★★
()
Последнее исправление: ymn (всего исправлений: 1)
Ответ на: комментарий от ymn

По ссылке не ходи - там все не првильно. От того что аффтар форкнул инициализацию процесс сервера не решит проблему - просто залипнет не процесс запускющий сервера, а сам сервер. Ему надо было стартонуть в handle_info отдельный процесс, который произведет инициализацию и пошлет ему месагу мол все путем я уже рабочий. Иначе у него просто залипнут все клиенты которые сделают call. А в это время сервер будет пребывать в состоянии пошли_нафик_я_еще_не_запустился. Ну разве чот залипон - требуемое поведение - но тогда непонятно зачем ее форкать в сервер - ну пусть запускается долго. Это лучше чем клиенты залипшие непонятно посредичего.

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

ymn

Да какие там парамерты? erl -run test start. test:start() супервайзер запускает для сервера, больше ничего.

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

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

r

В общем сделал маленький примерчик, где наблюдаеться такое поведение. Порт возвращает случайное число, или ставит random seed, в зависимости от того, что ему шлют.

Повторю, если запускать так: erl -run rand start, то порт вылетает, и пишет, что error: read() return 0. Если просто запустить вм и в интерактивном режиме сделать rand:start(), то всё стартует и работает на ура.

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

Во первых что собственно тебе не нравится? ну вернул read 0 - это нормальня ситуация. Зачем ты терминейтнул процесс? Во вторых зачем ты форкнул порт в еще более другой процесс чем серв? Или наоборот - зачем тебе ген_сервер для этого если есть другой процесс со своеим месседжингом? Одон из них лишнее.

r ★★★★★
()
Последнее исправление: r (всего исправлений: 1)
Ответ на: комментарий от r

Ну естественно, рассматривается count > 0; не вижу, как в цикле могла бы возникнуть ситуация с count == 0.

И есть другие случаи когда 0 это совсем не EOF: http://pubs.opengroup.org/onlinepubs/007908775/xsh/read.html

Про STREAMS лень даже читать - слишком нерелевантно.

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

не вижу, как в цикле

Вот сюда посмотри.

https://bitbucket.org/nanoo_linux/rand_server/src/95eb4e46f83abeb9576580f133d...

Если он считал длину месседжа 0, то дальше пробует прочитать 0 байт...

Про STREAMS лень даже читать - слишком нерелевантно.

Не про streams, а про чтение за пределами. В эрланге к стати есть бага на эту тему которую сопротивляются исправлять.

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

https://bitbucket.org/nanoo_linux/rand_server/src/95eb4e46f83abeb9576580f133d...

Если он считал длину месседжа 0, то дальше пробует прочитать 0 байт...

Насколько я понимаю, при len_ == 0 управление просто не войдет в цикл.

чтение за пределами

Это и есть EOF.

tailgunner ★★★★★
()
Последнее исправление: tailgunner (всего исправлений: 1)
Ответ на: комментарий от tailgunner

Насколько я понимаю, len_ == 0, управление просто не войдет в цикл.

Угу - увидел.

Это и есть EOF.

Не совсем. Если файл открыт то ему можно сделать seek за пределы физичски записанного пространства. read будет возвращать 0. Но это не совсем EOF, если параллельнйы процесс допишет файл...

Но тут дело в другом. rand_server сам стартует - что-то не так с супервизором. Его вообще нельзя так запускать - он должен линкнуться к аппликейшен мастеру - чего тут не происходит, за отсутствием оного. Топикстартер - напиши нормальный аппликейшен и стартуй его через application:start, хватит хакать OTP.

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

Одон из них лишнее.

А как мне тогда сообщения из порта ловить? В handle_call делать receive {Port, {data, Data}} -> ... ?

В esyslog так и сделано в общем-то, только там портов нету и init один коннект отрабатывает, но потом всё равно завершается.

ну вернул read 0 - это нормальня ситуация.

Это где-то описано в доках?

Если stdin привязан к какому-нибудь дескриптору pipe внутри вм, то ноль может возникнуть когда его закрыли например. Мне не совсем понятно зачем это делать. Кроме того, этот случай невозможно отличить от момента, когда вм завершили, или даже просто убили сервер exit(Server, kill) например. Тогда вопрос: нафига мне висящий процесс, который жрёт 100% кпу и ничего не делает? Что с ним делать?

Собственно я по-этому и завершаю процесс, если ноль.

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

Дык порт же на сях и написан.

0 - это ещё когда pipe() с другой стороны закрыли. man 7 pipe

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

А как мне тогда сообщения из порта ловить? В handle_call делать receive {Port, {data, Data}} -> ... ?

А какая разница висишь ты на ресиве от процесса висящего на ресиве или висишь на одном ресиве?

Тебе тут генсерв вообще не нужен.

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

Да, ты оказался прав. Прикрутил application и убрал процесс для порта, шлю сообщения прямо из handle_call и жду ответ. После этих изменений всё вроде работает прямо со старта, никаких нулей.

Честно говоря, меня это немного удивило, я думал супервайзеры и сервера могут и сами по себе работать. Походу нет.

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

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

r ★★★★★
()
Последнее исправление: r (всего исправлений: 1)
Ответ на: комментарий от r

Но всё равно не без изменений. У меня он работает только если не start_link, а просто start делать в rand_server:start/0. Со start_link сразу же завершается после старта. Хотя в принципе в доках так и написано.

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