nixp.ru v3.0

17 октября 2017,
вторник,
06:56:40 MSK

DevOps с компанией «Флант»
Аватар пользователя rgo
rgo написал 24 апреля 2010 года в 10:52 (1192 просмотра) Ведет себя неопределенно; открыл 61 тему в форуме, оставил 1602 комментария на сайте.

Чё за хрень творится, когда окно перетаскивается? Наблюдаемые эффекты:

1. Блокирование процесса, который это окно создал. Моментально, прямо в select’е на сокете X’ов. Объяснить это отсутствием данных в сокете нельзя, поскольку во время перетаскивания перестают прилетать SIGALRM, которые в нормальном режиме из select’а регулярно выкидывали с ошибкой EINTR. Я подумываю о том, что может быть SIGSTP прилетает, но SIGSTP может объяснить всё происходящее? И блокирование в сокете и откладывание очередного SIGALRM’а «на попозже»?

2. Блокирование всех остальных процессов. Это вероятно дело рук wm. Если запустить mplayer, то картинка его замирает моментально — это ещё ладно. Но через некоторое время останавливается и звук. Может просто из-за того, что mplayer пишет-пишет в X’овый сокет, а X-сервер не читает, и когда ядерный буфер переполняется, mplayer блокируется. Но это лишь гадания на кофейной гуще.

Собственно я даже не знаю о чём спросить. Дело ли это рук wm? Или это неотъемлимое свойство X’ов? Что X’ы делают с моим процессом, когда его окно перетаскивается? Может где-нибудь есть общее описание архитектуры графической системы X, но достаточно подробное, чтобы можно было бы объяснить результаты моих наблюдений?

Я попробую, конечно, выкинуть event-loop процесса в отдельный ядерный поток, но мне не нравится эта идея: я так долго парился над тем, чтобы запихать в один поток event-loop, цикл чтения звука из alsa и цикл записи звука в alsa, выверяя все задержки, что мне совсем уныло будет теперь переходить к заурядному по-потоку-на-сокет.

myst

Страдал мультиплексированием и напоролся на то же, на что напоролись перцы из MPlayer. Но MPlayer-mt так и не осилили. Да, многопоточность — это геморрой при отладке, но в условиях мультиядерности делать по-другому бессмысленно. По теме: никакой блокировки процесса быть не должно. WM работает в отдельном процессе и перемещения полностью контролирует он (ресайз — другое дело), т.е. X-ы не блокируются на перемещении и исправно выгребают инфу из сокета. Тут могут быть нюансы, конечно, я сам деталей не знаю, но я проверил на MPlayer — не блокируется. OpenBSD 4.6 / cwm

rgo

Посмотрел strace’ом, SIGALRM’ы прилетают. Во время перетаскивания вот такая шляпа в цикле:

12:40:22 -— SIGALRM (Alarm clock) @ 0 (0) ---
12:40:22 rt_sigaction(SIGALRM, {0x402180, [ALRM], SA_RESTORER|SA_RESTART, 0x7f94adb7a3a0}, {0x402180, [ALRM], SA_RESTORER|SA_RESTART, 0x7f94adb7a3a0}, 8) = 0
12:40:22 rt_sigreturn(0xe) = -1 EINTR (Interrupted system call)
12:40:22 poll([{fd=4, events=POLLIN}], 1, -1) =? ERESTART_RESTARTBLOCK (To be restarted)

Откуда sigaction и sigreturn — это дело рук моего обработчика и glibc. А вот откуда poll… Это, наверное, откуда-то из недр Xlib (4 — это дескриптор сокета Xlib), куда процесс передал управление.

Мне просто принципиально не нравится заводить много потоков из-за ввода/вывода. На производительности это не скажется, будь там хоть тыщща ядер, ведь сам ввод/вывод программы, в том числе и рисование графика сигнала времени практически не занимает. Тормозом будет в fft, но если он будет не просто тормозом, но существенным тормозом, то вот его я и раскидаю по потокам/ядрам/процессорам. Заведу под него пул потоков и буду им раздавать задания. А разбрасывание по потокам ввода/вывода, по-моему, больше замедлит систему добавив записей в очередь задач ядерного планировщика.

myst

Страдал мультиплексированием и напоролся на то же, на что напоролись перцы из MPlayer. Но MPlayer-mt так и не осилили.

А ссылка есть? Или хотя бы кейворды для гугла? :)

myst

я проверил на MPlayer — не блокируется. OpenBSD 4.6 / cwm

То есть, если начать перетаскивать окно (любое, не обязательно окно mplayer’а), и подержать его в «подвешенном» состоянии секунд 10, то звук не пропадает?

myst
  1. strace со слетевшим форматированием. Я ничего не понял. Это тебе не старый nixp, тут тэгов нет. What You See Is All You Get.
  2. Ссылки нет. Был одно время такой форк пару лет назад, но потом его прибили. Сейчас уже и из интернетов выпилили, как я погляжу. Гуглил, ничего не нашёл.
  3. Тягал секунд 20, но постоянно перемещал. Были и звук и видео, причём синхронизация не сбивалась. Проверял на AVI «House M.D» от LostFilm.
rgo
myst

 

  1. strace со слетевшим форматированием. Я ничего не понял. Это тебе не старый nixp, тут тэгов нет. What You See Is All You Get.

 

Я понял что со слетевшим. Но там всё просто:

SIGALRM

rt_sigaction

rt_sigreturn

poll

Я пользуюсь не poll’ом, а select’ом. Поскольку poll на дескрипторе Xlib, получается что кроме Xlib больше и некому поллить. Вот же сволочь какая, а?

Да, я понял, наконец. Я решил что процесс блокируется на селекте, разглядывая вывод программы в терминал, в процессе перетаскивания. Но, к тому моменту я ещё не успел обратить внимания на то, что окна не перерисовываются во время перетаскивания.

Это всё небось XPending, какой-нибудь. Но да ладно, это уж я как-нибудь расковыряю. Просто с этой неверной гипотезой о заблокированном select’е я в тупик залез, и не знал как оттуда вылезать. В конце-концов, нефиг окна тягать.

myst
  1. Тягал секунд 20, но постоянно перемещал. Были и звук и видео, причём синхронизация не сбивалась. Проверял на AVI «House M.D» от LostFilm.

 

Загадочно… Буду проверять. То ли дело во fluxbox’е, то ли в mplayer’е.

Провёл эксперимент, запустил mplayer с опцией -vo sdl. Теперь звук прерывается иначе — он прерывается почти сразу. Задержка есть, но она минимальна, на слух .1-.5 секунды. При дефолтном -vo xv, задержка измеряется секундами, максимум наверное где-то около 3-4 секунд.

myst

Думается мне, дело в вашей линупсячей ALSA.

rgo

Ты про mplayer? Не знаю. Вряд ли. Любопытно что задержка меняется в зависимости от -vo. Выглядит будто mplayer использует разный размер периода alsa в зависимости от метода вывода.

Если же ты про мою программу, то однозначно нет. Последние эксперименты я проводил на другой программке, которая с alsa не работает, зато постоянно тыкает себя сигналом SIGALRM. Да и то, что программка висит в poll на сокете X’ов — это однозначное указание на проблемы с Xlib.

Я всё же склоняюсь к мысли, что дело в wm. В пользу этого говорит то, что организация процесса перетаскивания окон — это его задача. Хотя я достаточно туманно представляю себе, как он может влиять. Какой бы wm поставить, чтоб проверить… cwm в ебилдах нету :) Так чтоль собрать… Интересно, он без make install пойдёт? Прям из директории где я его соберу.

myst

Должон работать. Он мелкий.

rgo

Добрался, наконец, до компа, продолжил эксперименты.

Итак, cwm вообще не работает. Подвешивает X’ы, причём так что приходится бежать до компа брательника, и оттуда через прибивать через ssh.

Программку я погонял, посчитал время вызовов всяких разных функций. Блокируется она где-то в своей функции draw, которая вызывается в связи с прилетевшим эвентом Expose. Точнее уж выяснять не вижу смысла, но в draw нет ничего кроме вызовов opengl. Причём и разнообразия-то особого нет, просто PushMatrix/PopMatrix, Translated/Rotated и glCallList. В связи с этой моей деятельностью возник вопрос: можно ли как-то из strace получить backtrace? У него промеж опций нету ничего такого, но может как-то можно исхитриться?

Но я понял-таки в чём хрень была. Во внутречерепном давлении: по-ходу мозг великоват и череп мне жмёт. Ответ на все вопросы я вычитал в FAQ к fluxbox. Это не баг, это фича. Если `session.screen0.opaqueMove: false’, то получаем именно то, что я описываю. Если же выставить в тру, то ничего не блокируется, все окошки шевелятся, в терминал летит поток отладочного флуда и всё просто чики-пуки. Кстати, после этого окно стало перетаскиваться не контуром, а именно окном (по-моему, раньше перетаскивалось контуром — я не обращал внимания).

Фак! Столько времени из-за такой хрени. Пора сносить fluxbox и искать что-нибудь попроще, с меньшим количеством настроек.

myst

Зачем тебе в strace backtrace?  Запусти gdb, влепи breakpoint и там получи свой bt [full].

rgo

Для этого надо влепить условный брекпойнт на poll. Брекпойнт который сработает на выходе из poll, причём только если между входом в poll и выходом из него прошло достаточно много времени. В моей ситуации это что-то около десятой секунды — именно с таким периодом мне прилетают SIGALRM’ы, которые прерывают заблокировавшийся poll.

 

Я так не умею. :(

 

myst

напиши после poll

if (time > max_time)
        *((int *)0) = 0;


Оно свалится в coredump. Потом загрузишь корку и посмотришь backtrace.