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