Eventfd with epoll BlockingIOError
Barry
barry at barrys-emacs.org
Thu Nov 25 03:47:46 EST 2021
> On 24 Nov 2021, at 23:09, Jen via Python-list <python-list at python.org> wrote:
>
> I have a C program that uses fork-execv to run Python 3.10 in a child process, and I am using eventfd with epoll for IPC between them. The eventfd file descriptor is created in C and passed to Python through execv. Once the Python child process starts I print the file descriptor to verify that it is correct (it is).
>
> In this scenario C will write to the eventfd at intervals and Python will read the eventfd and take action based on the value in the eventfd. But in the Python while True loop I get "BlockingIOError: [Errno 11] Resource temporarily unavailable" then with each new read it prints "Failed epoll_wait Bad file descriptor."
>
> This is the Python code:
>
> #!/usr/bin/python3
> import sys
> import os
> import select
>
> print("Inside Python")
>
> event_fd = int(sys.argv[3])
>
> print("Eventfd received by Python")
> print(event_fd)
>
> ep = select.epoll(-1)
> ep.register(event_fd, select.EPOLLIN | select.EPOLLOUT)
>
> event_write_value = 100
>
> while True:
>
> print("Waiting in Python for event")
> ep.poll(timeout=None, maxevents=- 1)
> v = os.eventfd_read(event_fd)
>
> if v != 99:
> print("found")
> print(v)
> os.eventfd_write(event_fd, event_write_value)
>
> if v == 99:
> os.close(event_fd)
>
> This is the C code that writes to Python, then waits for Python to write back:
>
> ssize_t epoll_write(int event_fd, int epoll_fd, struct epoll_event * event_struc, int action_code)
> {
> int64_t ewbuf[1];
> ewbuf[0] = (int64_t)action_code;
> int maxevents = 1;
> int timeout = -1;
>
> fprintf(stdout, " Writing to Python \n%d", event_fd);
>
> write(event_fd, &ewbuf, 8);
>
> if (epoll_wait(epoll_fd, event_struc, maxevents, timeout) == -1)
> {
> fprintf(stderr, "Failed epoll_wait %s\n", strerror(errno));
> }
>
> ssize_t rdval = read(event_fd, &ewbuf, 8);
>
> fprintf(stdout, " Received from Python \n%ld", rdval);
>
> return 0;
> }
>
> This is the screen output when I run with gdb:
>
> Inside Python
> Eventfd received by Python
> 5
> Waiting in Python for event
> Traceback (most recent call last):
> File "/usr/local/lib/python3.10/runpy.py", line 196, in _run_module_as_main
> return _run_code(code, main_globals, None,
> File "/usr/local/lib/python3.10/runpy.py", line 86, in _run_code
> exec(code, run_globals)
> File "/opt/P01_SH/NPC_CPython.py", line 36, in <module>
> v = os.eventfd_read(event_fd)
> BlockingIOError: [Errno 11] Resource temporarily unavailable
> Writing to Python
> 5 Received from Python
> 8 Writing to Python
> Failed epoll_wait Bad file descriptor
> 5 Received from Python
> 8 Writing to Python
> Failed epoll_wait Bad file descriptor
> 5 Received from Python
> -1time taken 0.000548
> Failed to close epoll file descriptor
> Unlink_shm status: Bad file descriptor
> fn() took 0.000648 seconds to execute
> [Inferior 1 (process 12618) exited normally]
> (gdb)
>
> So my question is why do I get "BlockingIOError: [Errno 11] Resource temporarily unavailable" and "Failed epoll_wait Bad file descriptor" from Python?
Is the fd set to non blocking? Try use fcntl to set the fd non blocking.
I am not sure if the non block state is inherited on a fork.
Do you have a C version of this code that works as a test?
Try running the python version under strace to see exactly what system calls are used.
Barry
>
> --
> Sent with Tutanota, the secure & ad-free mailbox.
> --
> https://mail.python.org/mailman/listinfo/python-list
More information about the Python-list
mailing list