void drakvuf_vmi_event_callback (int fd, void* data)
{
UNUSED(fd);
drakvuf_t drakvuf = *(drakvuf_t*) data;
status_t status = vmi_events_listen(drakvuf->vmi, drakvuf->poll_rc);
if (VMI_SUCCESS != status)
{
PRINT_DEBUG("Error waiting for events or timeout, quitting...\n");
drakvuf->interrupted = -1;
}
}Inside drakvuf_init :
/* register the main VMI event callback */
drakvuf_event_fd_add(*drakvuf, (*drakvuf)->xen->evtchn_fd, drakvuf_vmi_event_callback, drakvuf);
PRINT_DEBUG("drakvuf_init: adding event_fd done\n");int drakvuf_event_fd_add(drakvuf_t drakvuf, int fd, event_cb_t event_cb, void* data)
{
PRINT_DEBUG("drakvuf_event_fd_add fd=%d\n", fd);
/* add new fd_info */
fd_info_t new_fd_info = (fd_info_t) g_try_malloc0(sizeof(struct fd_info));
new_fd_info->fd = fd;
new_fd_info->event_cb = event_cb;
new_fd_info->data = data;
/* the event_fd_info list is the authoritive data source used to
create the event_fds and fd_info_lookup data structures */
drakvuf->event_fd_info = g_slist_append(drakvuf->event_fd_info, new_fd_info);
drakvuf->event_fd_cnt = g_slist_length(drakvuf->event_fd_info);
PRINT_DEBUG("size of list=%d\n", drakvuf->event_fd_cnt);
PRINT_DEBUG("regenerating event_fds and fd_info_lookup...\n");
drakvuf_event_fd_generate(drakvuf);
return 1;
}static void drakvuf_event_fd_generate(drakvuf_t drakvuf)
{
/* event_fds and fd_info_lookup are both generated based off of
drakvuf->event_fd_info */
if (drakvuf->event_fds != NULL)
{
PRINT_DEBUG("freeing existing event_fds\n");
g_free(drakvuf->event_fds);
}
if (drakvuf->fd_info_lookup != NULL)
{
PRINT_DEBUG("freeing existing fd_info_lookup\n");
g_free(drakvuf->fd_info_lookup);
}
/* allocate and populate new pollfd array and new fd_info_lookup array */
drakvuf->event_fds = (struct pollfd*) g_try_malloc0(sizeof(struct pollfd) * \
(g_slist_length(drakvuf->event_fd_info)));
drakvuf->fd_info_lookup = (fd_info_t) g_try_malloc0(sizeof(struct fd_info) * \
(g_slist_length(drakvuf->event_fd_info)));
int i = 0;
GSList* loop = drakvuf->event_fd_info;
while (loop)
{
fd_info_t fd_info = (fd_info_t) loop->data;
drakvuf->event_fds[i].fd = fd_info->fd;
drakvuf->event_fds[i].events = POLLIN | POLLERR;
PRINT_DEBUG("new event_fd i=%d for fd=%d\n", i, fd_info->fd);
drakvuf->fd_info_lookup[i].fd = fd_info->fd;
drakvuf->fd_info_lookup[i].event_cb = fd_info->event_cb;
drakvuf->fd_info_lookup[i].data = fd_info->data;
PRINT_DEBUG("new fd_info_lookup i=%d for fd=%d\n", i, fd_info->fd);
loop = loop->next;
i++;
}
return;
}The events are consumed and the callback is executed in a loop, the main loop of drakvuf application:
void drakvuf_loop(drakvuf_t drakvuf, bool (*is_interrupted)(drakvuf_t, void*), void* data)
{
PRINT_DEBUG("Started DRAKVUF polling loop\n");
drakvuf->interrupted = 0;
drakvuf_force_resume(drakvuf);
while (!is_interrupted(drakvuf, data))
drakvuf_poll(drakvuf, 1000);
vmi_pause_vm(drakvuf->vmi);
// Ensures all events are processed from the ring
drakvuf_poll(drakvuf, 0);
PRINT_DEBUG("DRAKVUF polling loop finished\n");
}static void drakvuf_poll(drakvuf_t drakvuf, unsigned int timeout)
{
int rc = poll(drakvuf->event_fds, drakvuf->event_fd_cnt, timeout);
drakvuf->poll_rc = rc;
if (!rc && timeout)
return;
else if (rc < 0)
{
PRINT_DEBUG("DRAKVUF loop broke unexpectedly: [Errno: %d] %s\n", errno, strerror(errno));
if (errno != EINTR)
{
drakvuf->interrupted = -1;
}
return;
}
/* check and process each fd if it was raised */
for (int poll_ix=0; poll_ix<drakvuf->event_fd_cnt; poll_ix++)
{
if (timeout && !(drakvuf->event_fds[poll_ix].revents & (POLLIN | POLLERR)) )
continue;
fd_info_t fd_info = &drakvuf->fd_info_lookup[poll_ix];
fd_info->event_cb(fd_info->fd, fd_info->data);
}
}