I'm so happy I could cry after being on a roller coaster
of trying to figure this out.
I came close to bailing a few times.


van:~/code/scm/cev$ ./main.exe add
add-event...
f:0x92ee931d220
cb2 (defined in scheme, and called in C)
cb_func_2 called 1 times.
cb2 (defined in scheme, and called in C)
cb2 (defined in scheme, and called in C)
cb2 (defined in scheme, and called in C)
cb2 (defined in scheme, and called in C)
cb2 (defined in scheme, and called in C)
cb2 (defined in scheme, and called in C)
cb2 (defined in scheme, and called in C)
cb2 (defined in scheme, and called in C)
cb2 (defined in scheme, and called in C)
cb2 (defined in scheme, and called in C)
^C



This is the libevent C library on OpenBSD ...
...
calling into scheme functions.
That output is from scheme code.
The libevent library is C and takes callbacks to
do it's event triggered stuff.
I defined a C compatible callback from scheme code.

I added an event callback that fires every second.
So that means libevent is running and every second
it executes a callback function that is written in scheme.

:)

This means I can do high level scheme stuff, and use
the low level libevent lib.
(I assume this would work with any C event lib like libev
or libuv, but as an OpenBSD zealout for the time
being I am using the one sanctioned by them.)

#openbsd #scheme #chicken #libevent
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