Can't integrate wayland event loop into another event loop (epoll)
I am newbie and probably doing something wrong, but I can't make wayland event loop work inside another event loop. Here is very minimal example.
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <wayland-server.h>
#include <sys/epoll.h>
#define MAX_EVENTS 32
void run_good(struct wl_display *display)
{
wl_display_run(display);
}
void run_bad(struct wl_display *display)
{
int epoll_fd;
struct wl_event_loop *loop;
int fd;
struct epoll_event ev;
struct epoll_event events[MAX_EVENTS];
int n;
epoll_fd = epoll_create(1);
if (epoll_fd == -1)
exit(-1);
loop = wl_display_get_event_loop(display);
fd = wl_event_loop_get_fd(loop);
ev.events = EPOLLIN;
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &ev) == -1)
exit(-1);
for (;;)
{
n = epoll_wait(epoll_fd, events, MAX_EVENTS, -1);
if (n == -1)
exit(-1);
fprintf(stdout, "EVENT\n");
for (int i = 0; i < n; ++i)
{
wl_display_flush_clients(display);
wl_event_loop_dispatch(loop, 0);
}
}
}
int main(int argc, char *argv[])
{
struct wl_display *display;
display = wl_display_create();
wl_display_add_socket_auto(display);
run_bad(display);
return 0;
}
If I start wayland's integrated event loop with run_good() everything works as expected. Well, at least "konsole" (Qt5 app) is able to connect and says "Running on a compositor with no screens is not supported".
But if I start my own loop with run_bad() everything behaves stangely: "EVENT" message got fired twice and client freezes. It feels like some events get stuck.
I can make everything look working by adding timer (repeating) to wayland integrated loop. When timer fires, it flushes stuck events somehow.
Example I provides may be to simple but nothing changes if I implement all protocols needed for my compositor to work.
I am using Fedora 28. Wayland version is 1.15.
Not sure this is important but I also have the same problem when trying to integrate wayland event loop into Android application's event loop (by passing fd to Java code and using addOnFileDescriptorEventListener).