Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ivykis aborts on FreeBSD 13.1 (kqueue) when a polled pipe fd gets closed #26

Open
OverOrion opened this issue Jun 29, 2022 · 6 comments

Comments

@OverOrion
Copy link

The attached reproducer code spawns two processes, one of them polls a perfectly valid pipe fd for writing using ivykis, and the child process would be responsible for reading, but for an easier reproduction, the child just closes the pipe and exits. (Reading and then closing would result in the same abort.)

https://gist.github.com/MrAnno/0a6dd9572e8a7a981996654ccd3e5e08

Running it yields the following backtrace:

[0] from 0x000000080039233a in thr_kill
[1] from 0x000000080030ac74 in raise
[2] from 0x00000008003bc109 in abort
[3] from 0x000000080024ecbb in iv_fatal+235 at iv_fatal.c:57
[4] from 0x0000000800256832 in iv_fd_kqueue_poll+1106 at iv_fd_kqueue.c:212
[5] from 0x0000000800251561 in iv_fd_poll_and_run+177 at iv_fd.c:206
[6] from 0x0000000800253a15 in iv_main+181 at iv_main_posix.c:112
[7] from 0x0000000000201de6 in main+198 at main.c:60

I believe ivykis incorrectly reports fatal errors in case a kevent() call returns EV_ERROR on the file description:

ivykis/src/iv_fd_kqueue.c

Lines 208 to 214 in f1b1455

if (batch[i].flags & EV_ERROR) {
int err = batch[i].data;
int fd = batch[i].ident;
iv_fatal("iv_fd_kqueue_poll: got error %d[%s] "
"polling fd %d", err, strerror(err), fd);
}

The epoll implementation, for example, reports these kind of errors as non-fatal using the error callback:

ivykis/src/iv_fd_epoll.c

Lines 185 to 186 in f1b1455

if (events & (EPOLLERR | EPOLLHUP))
iv_fd_make_ready(active, fd, MASKERR);

@buytenh
Copy link
Owner

buytenh commented Jan 30, 2024

The gist.github.com link gives a 404 -- can you repost the reproducer somewhere? (Preferably verbatim in a comment in this issue.)

@bazsi
Copy link
Contributor

bazsi commented Jun 2, 2024

@OverOrion do you still happen to have the reproducer for this?

@OverOrion
Copy link
Author

Unfortunately not :(

@buytenh
Copy link
Owner

buytenh commented Jun 17, 2024

@MrAnno Do you still have the reproducer, given that it was posted under your gist.github.com?

@MrAnno
Copy link

MrAnno commented Jun 30, 2024

I don't have it, but I think I remember what to do.
I'll try to recreate the reproducer next week.

@MrAnno
Copy link

MrAnno commented Jun 30, 2024

#0  0x000000080058b41a in thr_kill () from /lib/libc.so.7
#1  0x0000000800504e64 in raise () from /lib/libc.so.7
#2  0x00000008005b56f9 in abort () from /lib/libc.so.7
#3  0x0000000800448a6e in iv_fatal (fmt=<optimized out>) at iv_fatal.c:57
#4  0x000000080044fcd4 in iv_fd_kqueue_poll (st=0x800c09000, active=0x7fffffffe960, abs=0x0) at iv_fd_kqueue.c:212
#5  0x000000080044b3e6 in iv_fd_poll_and_run (st=0x800c09000, abs=0x0) at iv_fd.c:205
#6  0x000000080044cf90 in iv_main () at iv_main_posix.c:112
#7  0x0000000000400d6e in main () at test.c:55
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <unistd.h>
#include <sys/wait.h>

#include <iv.h>

void fatal(const char* msg)
{
    perror(msg);
    exit(1);
}

void write_fd(void* c)
{
    struct iv_fd* fd = (struct iv_fd*) c;

    const char* buf = "hello\n";
    int rc = write(fd->fd, buf, strlen(buf) + 1);

    if (rc < 0)
        iv_fd_unregister(fd);
}

int main()
{
    iv_init();

    int pp[2];
    if (pipe(pp) < 0)
        fatal("pipe()");

    pid_t pid = fork();

    if (pid < 0)
        fatal("fork()");

    if (pid == 0) {
        close(pp[1]);
        close(pp[0]);
        return 0;
    }

    close(pp[0]);

    struct iv_fd fd;
    IV_FD_INIT(&fd);
    fd.fd = pp[1];
    fd.cookie = &fd;
    fd.handler_out = write_fd;
    iv_fd_register(&fd);

    iv_main();
    iv_deinit();

    close(pp[1]);

    int rc;
    if (wait(&rc) < 0)
        fatal("wait()");

    return 0;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants