> On 5 Dec 2021, at 17:54, Jen Kris <jenk...@tutanota.com> wrote: > > > Thanks for your comments. > > I put the Python program on its own pthread, and call a small C program to > fork-execv to call the Python program as a child process.
What do you mean by putting python in it’s own pthread? Are you embedding python in an other program? Barry > I revised the Python program to be a multiprocessing loop using the Python > multiprocessing module. That bypasses the GIL and allows Python to run > concurrently with C. So far so good. > > Next I will use Linux pipes, not Python multiprocessing pipes, for IPC > between Python and C. Multiprocessing pipes are (as far as I can tell) only > for commo between two Python processes. I will have the parent thread send a > signal through the pipe to the child process to exit when the parent thread > is ready to exit, then call wait() to finalize the child process. > > I will reply back when it's finished and post the code so you can see what I > have done. > > Thanks again. > > Jen > > > Dec 4, 2021, 09:22 by ba...@barrys-emacs.org: > >>> On 1 Dec 2021, at 16:01, Jen Kris <jenk...@tutanota.com> wrote: >>> >>> Thanks for your comment re blocking. >>> >>> I removed pipes from the Python and C programs to see if it blocks without >>> them, and it does. >>> It looks now like the problem is not pipes. >> >> Ok. >> >> I use fork() and execv() in C to run Python in a child process, but the >> Python process blocks > > Use strace on the parent process to see what is happening. > You will need to use the option to follow subprocesses so that you can see > what goes on in the python process. > > See man strace and the --follow-forks and --output-separately options. > That will allow you to find the blocking system call that your code is making. > >> because fork() does not create a new thread, so the Python global >> interpreter lock (GIL) prevents the C program from running once Python >> starts. > > Not sure why you think this. > >> So the solution appears to be run Python in a separate thread, which I can >> do with pthread create. >> See "Thread State and the Global Interpreter Lock" >> https://docs.python.org/3/c-api/init.html#thread-state-and-the-global-interpreter-lock >> and the sections below that "Non-Python created threads" and "Cautions >> about fork()." > > I take it you mean that in the parent you think that using pthreads will > affect python after the exec() call? > I does not. After exec() the process has one main thread create by the kernel > and a new address space as defined by the /usr/bin/python. > The only state that in inherited from the parent are open file descriptors, > the current working directory and security state like UID, GID. > >> I'm working on that today and I hope all goes well :) > > You seem to be missing background information on how processes work. > Maybe "Advanced Programming in the UNIX Environment" would be helpful? > > https://www.amazon.co.uk/Programming-Environment-Addison-Wesley-Professional-Computing-dp-0321637739/dp/0321637739/ref=dp_ob_image_bk > > > It's a great book and covers a wide range of Unix systems programming topics. > > Have you created a small C program that just does the fork and exec of a > python program to test out your assumptions? > If not I recommend that you do. > > Barry > > >> >> >> >> Nov 30, 2021, 11:42 by ba...@barrys-emacs.org: >> >> >>> On 29 Nov 2021, at 22:31, Jen Kris <jenk...@tutanota.com> wrote: >>> >>> Thanks to you and Cameron for your replies. The C side has an epoll_ctl >>> set, but no event loop to handle it yet. I'm putting that in now with a >>> pipe write in Python-- as Cameron pointed out that is the likely source of >>> blocking on C. The pipes are opened as rdwr in Python because that's >>> nonblocking by default. The child will become more complex, but not in a >>> way that affects polling. And thanks for the tip about the c-string >>> termination. >>> >> >> flags is a bit mask. You say its BLOCKing by not setting os.O_NONBLOCK. >> You should not use O_RDWR when you only need O_RDONLY access or only >> O_WRONLY access. >> >> You may find >> >> man 2 open >> >> useful to understand in detail what is behind os.open(). >> >> Barry >> >> >> >>> >>> >>> Nov 29, 2021, 14:12 by ba...@barrys-emacs.org: >>> >>> On 29 Nov 2021, at 20:36, Jen Kris via Python-list <python-list@python.org> >>> wrote: >>> >>> I have a C program that forks to create a child process and uses execv to >>> call a Python program. The Python program communicates with the parent >>> process (in C) through a FIFO pipe monitored with epoll(). >>> >>> The Python child process is in a while True loop, which is intended to keep >>> it running while the parent process proceeds, and perform functions for the >>> C program only at intervals when the parent sends data to the child -- >>> similar to a daemon process. >>> >>> The C process writes to its end of the pipe and the child process reads it, >>> but then the child process continues to loop, thereby blocking the parent. >>> >>> This is the Python code: >>> >>> #!/usr/bin/python3 >>> import os >>> import select >>> >>> #Open the named pipes >>> pr = os.open('/tmp/Pipe_01', os.O_RDWR) >>> Why open rdwr if you are only going to read the pipe? >>> pw = os.open('/tmp/Pipe_02', os.O_RDWR) >>> Only need to open for write. >>> >>> ep = select.epoll(-1) >>> ep.register(pr, select.EPOLLIN) >>> >>> Is the only thing that the child does this: >>> 1. Read message from pr >>> 2. Process message >>> 3. Write result to pw. >>> 4. Loop from 1 >>> >>> If so as Cameron said you do not need to worry about the poll. >>> Do you plan for the child to become more complex? >>> >>> while True: >>> >>> events = ep.poll(timeout=2.5, maxevents=-1) >>> #events = ep.poll(timeout=None, maxevents=-1) >>> >>> print("child is looping") >>> >>> for fileno, event in events: >>> print("Python fileno") >>> print(fileno) >>> print("Python event") >>> print(event) >>> v = os.read(pr,64) >>> print("Pipe value") >>> print(v) >>> >>> The child process correctly receives the signal from ep.poll and correctly >>> reads the data in the pipe, but then it continues looping. For example, >>> when I put in a timeout: >>> >>> child is looping >>> Python fileno >>> 4 >>> Python event >>> 1 >>> Pipe value >>> b'10\x00' >>> The C code does not need to write a 0 bytes at the end. >>> I assume the 0 is from the end of a C string. >>> UDS messages have a length. >>> In the C just write 2 byes in the case. >>> >>> Barry >>> child is looping >>> child is looping >>> >>> That suggests that a while True loop is not the right thing to do in this >>> case. My question is, what type of process loop is best for this situation? >>> The multiprocessing, asyncio and subprocess libraries are very extensive, >>> and it would help if someone could suggest the best alternative for what I >>> am doing here. >>> >>> Thanks very much for any ideas. >>> >>> >>> -- >>> https://mail.python.org/mailman/listinfo/python-list >>> >> >> > > -- https://mail.python.org/mailman/listinfo/python-list