> On 5 Dec 2021, at 23:51, Jen Kris <jenk...@tutanota.com> wrote:
> 
> 
> By embedding, I think you may be referring to embedding Python in a C program 
> with the Python C API.   That's not what I'm doing here -- I'm not using the 
> Python C API.  The C program creates two threads (using pthreads), one for 
> itself and one for the child process.  On creation, the second pthread is 
> pointed to a C program that calls fork-execv to run the Python program.  That 
> way Python runs on a separate thread.  The multiprocessing library 
> "effectively side-step[s] the Global Interpreter Lock by using subprocesses 
> instead of threads."  https://docs.python.org/3/library/multiprocessing.html. 
>  This way I can get the Python functionality I want on call from the C 
> program through pipes and shared memory.  
> 
> I don't want to use the C API because I will be making certain library calls 
> from the C program, and the syntax is much easier with native Python code 
> than with C API code. 
> 
> I hope that clarifies what I'm doing. 

You are confusing the threading needs of a python program and extension written 
in C
and what you need to do to start a child process.

I see no benifit from calling fork and exec from a new thread. Indeed you may
encounter more issues.

What ever the bug is that you and trying to fix threading has nothing to do 
with it.

What if you change you code to run bash script instead of python?
Does you C program block them?

What did strace tell you was the reason that your C parent program blocked?

Barry



> 
> Jen
> 
> 
> 
> Dec 5, 2021, 15:19 by ba...@barrys-emacs.org:
> 
> 
> 
>>> 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

Reply via email to