This might (and does to me) seem obvious in hindsight.

But learning to program in #C and learning #ncurses AND
using #libevent made it not obvious.

Like I am refactoring constantly in this state of learning and
programming. I build up working code, and then see some
bad patterns and throw whole sections away and re-work them.

So I was at a place where the other stuff was relatively organized
and I liked how the app was working, but the screen was flickering.

And IME so far ncurses WINDOW(s) are not localized enough to
ameliorate that. To be clear I was only clearing my main WINDOW,
but the whole screen would flicker. That is why I am leaning towards
just not using clear and/or minimizing it.

It's also interesting too that I use tmux.
tmux also uses libevent and ncurses? but doesn't flicker.
But I am not comparing what I am doing to tmux :)
It's just interesting.
Пример типичной системно-прикладной разработки, реализация своей «очереди сообщений» (event loop).
Использованием
#epoll, вместо «традиционных» select & poll, для асинхронной работы через polling’а (и мультиплексирования).

Отслеживание файловых дескрипторов через
#epoll выглядит более современно, меньше копирования памяти между user space и kernel space. А при появлении ожидаемых данных можно напрямую переходить к объекту или структуре данных, что важно при наблюдении за несколькими файлами и\или соединениями. Устраняется поиск «сработавшего» файлового дескриптора в индексных массивах, полноценное О(1) во всех случаях. Можно сразу же работать с теми экземплярами объектов, которые оборачивают тот файл или udp-поток, tcp-, quic-соединение, где появились новые данные.

Есть несколько готовых к использованию «очередей сообщений» (event loop'ов) —
#libev, #libuv, #libevent. Для некоторых агент-серверные решений и брокера #RabbitMQ это подходит. Однако, в некоторых случаях AMQP-библиотеки не скрещиваются с уже готовыми «очередями сообщений». Потому что агентская часть может активно использовать асинхронно-реактивное программирование с хорошей и проверенной «горизонтальной масштабируемостью». Т.е. на агентской части выполняется много работы и реализация сделана через sharing nothing многопоточность. Это такая парадигма, когда не просто достигается не только горизонтальная масштабируемость через lock-free\wait-free, а так же исключается много вредного, как тот же cache ping-pong или false sharing. Внутри агентов идёт своё управление потоками с выделениями памяти. Не только в плане «динамической памяти» (heap, аллокаторы а-ля #jemalloc от #Facebook), но и приколами вокруг pinning страниц, учёта #NUMA и даже huge pages(меньше промахов в #TLB).

Почему бы не использовать epoll?
Библиотека не обязана вычитывает данные целиком из потока (сокета), а может забирает данные лишь до тех пор, пока не насытится автомат состояний (finite-state machine). Например, выполняется парсинг сущностей AMQP-протокола, которые, по мере накопления, передаются в обработчики указанные клиентом библиотеки.
И это плохо соотносится с тем, что используя
#epoll надо выбирать какой вариант оповещений использовать:
• «по уровню» (level-triggered),
• «по фронту» (edge-triggered).

Особенности поведения отдельно взятой библиотеки может не позволять использовать работу «по фронту» (edge-triggered), т.к. библиотека не вычитывает полностью все данные из файловых дескрипторов.

Можно быть хоть пять раз technical lead и всё это прекрасно знать, но следует помнить, что как только в коде появляется флаг EPOLLET, то необходимо проводить аудит работы с потоками данных. Это избавляет команду от многих заморочек вокруг тестирования и ковыряния с каким-то совершенно непонятным поведением кода.

Про
«Edge Triggered Vs Level Triggered interrupts»

#programming #linux #softdev #трудовыебудни
Edge Triggered Vs Level Triggered interrupts

Discussion: Level triggered: as long as the IRQ line is asserted, you get an interrupt request. When you serve the interrupt and return, ...

К вопросу использования #epoll вместо хорошо знакомых и «традиционных» select & poll. Т.е. асинхронной работы с чем-либо посредством polling’а и мультиплексирования.

Недавно пришлось заниматься реализацией очереди событий для AMQP-CPP. В одном из продуктов решено сделать связь агентских частей с основным «контроллером» через #AMQP, в качестве брокера #RabbitMQ (всё стандартно, обычный кластер и TLS-соединения).

Вот только агенты продукта активно используют асинхронно-реактивное программирование с хорошей «горизонтальной масштабируемостью». Когда достигнуто полноценное sharing nothing, не просто горизонтальная масштабируемость через lock-free или wait-free и закон Амдала. Исключается много всего и сразу, как старый-добрый cache ping-pong, так и печаль с false sharing.

Отсюда внутри агентов и своё управление потоками с выделениями памяти. Не только в плане heap (динамической памяти, со своими аллокаторами а-ля #jemalloc от #Facebook), но и приколы вокруг узлов #NUMA и даже huge pages (снижающих «давление» на #TLB, меньше промахов).

Первая же проблема выплыла почти сразу — не реально использовать библиотеку AMQP-CPP с уже предоставляющейся поддержкой #libev, #libuv, #libevent. Несовместимы эти очереди сообщений с имеющейся моделью управления потоками и организации задач на агентах.

Почему был взят epoll

Подход используемый в #epoll выглядит более современно, меньше копирований памяти между user space и kernel space. А при появлении данных в отслеживаемом файловом дескрипторе можно напрямую перейти по указателю на объект класса или структуру данных. Тем самым обходиться без поиска дескриптора по индексным массивам/контейнерам. Сразу же работать с экземплярами объектов оборачивающих нужное #tcp -соединение, того самого, в которое и пришли данные.

И тут обозначилась вторая проблема, что используема AMQP-библиотека не вычитывает данные целиком из потока сокета. Например, забирает данные лишь до тех пор, пока не насытится автомат состояний (finite-state machine), выполняющий парсинг сущностей AMQP-протокола.

Используя #epoll приходится выбирать на какой вариант обработки событий ориентироваться:

  • срабатывание оповещений «по уровню» (level-triggered),
  • выбрасывания событий «по фронту» (edge-triggered).

И беда с библиотекой в очередной раз показала, что нельзя использовать работу «по фронту» (edge-triggered) не изучив досконально работу подсистемы отвечающей за вычитывание данных из файловых дескрипторов. И появление флага EPOLLET в коде является маркером, о том, чтобы проводить аудит использовавшихся решений.

Про Edge Triggered Vs Level Triggered interrupts можно почитать в https://venkateshabbarapu.blogspot.com/2013/03/edge-triggered-vs-level-triggered.html)

#programming #linux #трудовыебудни

Akkoma

#tmux wykrzacza się z #libevent 2.2.1 (alpha). Niestety, komunikat błędu wypisywany jest na nowym terminalu, a tmux od razu go zamyka i czyści ekran.

Próbowałem wydostać tekst poprzez przekierowanie wyjścia, poprzez logi tmuksa, nie udało się nawet przy pomocy strace (!). Dopiero #asciinema dało radę.

Kolejne zastosowanie dla tego świetnego programu. Szczerze polecam!

https://github.com/tmux/tmux/issues/3572

#Gentoo

Assertion ret == 0 failed in sigfd_free_sigevent with libevent-2.2.1 · Issue #3572 · tmux/tmux

Issue description After rebuilding tmux against libevent-2.2.1-alpha (we're testing to catch early issues), tmux is crashing immediately after opening a new session, with the following assertion: /...

GitHub

#tmux crashes with #libevent 2.2.1 (alpha). However, the assertion message only gets printed inside the new terminal, and tmux closes it immediately and clears the screen.

I couldn't manage to get the message via redirecting output, via tmux logs, even via strace (!). Finally, I've figured out to use #asciinema.

Another great use case for this great program. Kudos!

https://github.com/tmux/tmux/issues/3572

#Gentoo

Assertion ret == 0 failed in sigfd_free_sigevent with libevent-2.2.1 · Issue #3572 · tmux/tmux

Issue description After rebuilding tmux against libevent-2.2.1-alpha (we're testing to catch early issues), tmux is crashing immediately after opening a new session, with the following assertion: /...

GitHub

Today's #Gentoo fun:

tmux fails to build with #libevent 2.2.1. It fails because of incompatible declaration of forkpty() in compat.h.

Looking into compat.h. forkpty() is declared there if HAVE_FORKPTY is false.

Looking into config.log. forkpty() is not found because configure tries to link random test programs to -levent_core@CMAKE_DEBUG_POSTFIX@.

At this point, you can guess what the problem is: https://github.com/libevent/libevent/issues/1459

#CMake #autotols

*.pc files have unexpanded `@CMAKE_DEBUG_POSTFIX@` when built via autotools · Issue #1459 · libevent/libevent

To reproduce: $ ./autogen.sh $ ./configure -C $ grep POSTFIX *.pc libevent_core.pc:Libs: -L${libdir} -levent_core@CMAKE_DEBUG_POSTFIX@ libevent_extra.pc:Libs: -L${libdir} -levent_extra@CMAKE_DEBUG_...

GitHub

#glibc 2.36 introduces arc4random(). This makes #libevent switch from bundled to system ARC4 when rebuilt. Good so far.

However, glibc doesn't support arc4random_addrandom(), so libevent… removes evutil_secure_rng_add_bytes() and changes its ABI, effectively breaking installed #Tor (#Gentoo is especially affected).

Upstream argues that leaving the function as no-op is bad for #security However, when it's gone, Tor just skips the call.

https://github.com/libevent/libevent/issues/1393
https://gitlab.torproject.org/tpo/core/tor/-/blob/main/src/lib/evloop/compat_libevent.c#L483-485

libevent failed to build from source on Debian Bookworm with glibc 2.36 · Issue #1393 · libevent/libevent

Hello, I'm digging up an old question about evutil_secure_rng_add_bytes. I'm maintaining the package libevent in Debian, and lately I had a failed to build from source (FTBFS) for libevent ...

GitHub

Oh, groovy!

Also thanks to @eborisch #libevent in #MacPorts now has a commit merged with a patch that is a *little* bit ahead of libevent's versioned release in order to ameliorate some issues with #LibreSSL noticed on versions above 3.5+ (this is related to what I was testing earlier today):

https://github.com/macports/macports-ports/pull/16681

Hopefully that helps folks who were running into issues such as documented in this Trac ticket: https://trac.macports.org/ticket/66096

libevent: Add upstream patch for libressl by jerryyhom · Pull Request #16681 · macports/macports-ports

close: https://trac.macports.org/ticket/66096 Description Upstream patch adds compatibility with libressl v3.5+. Type(s) bugfix enhancement security fix Tested on The patch comes from upst...

GitHub

(Casually wonders why #MacPorts has
#libevent
https://ports.macports.org/port/libevent/ [more or less current with upstream]

and
#libevent1

https://ports.macports.org/port/libevent1/ [what is this doing here? I am so confused. Though obviously has some different things which depend on it such as honeyd, also by Niels Provos. So: maybe old and crufty stuff needs older libevent1?] )

Install libevent on macOS with MacPorts

There's still this #libevent diff that I have been meaning to test: https://github.com/macports/macports-ports/pull/16681/files

I have definitely noticed some occasional oddities with #LibreSSL vis-à-vis libevent, so hopefully that rectifies them?

#MacPorts

libevent: Add upstream patch for libressl by jerryyhom · Pull Request #16681 · macports/macports-ports

close: https://trac.macports.org/ticket/66096 Description Upstream patch adds compatibility with libressl v3.5+. Type(s) bugfix enhancement security fix Tested on The patch comes from upst...

GitHub