Home > Enterprise >  Why do only two of the three pipes write between the processes in Python?
Why do only two of the three pipes write between the processes in Python?

Time:06-16

I'm currently working on a project where I have to use os.pipe() and os.fork() in Python. I have alread set up the processes with the fork function so I (should) have one parent with two children, from which one has a children on it's own.

In the first version of my code, it seems that only two of three pipes were read:

import os
import random



pid=os.fork()

r, w = os.pipe()
r2, w2 = os.pipe()
r3, w3 = os.pipe()

if pid != 0:

    pid2=os.fork()
    
    if pid2 != 0:

        print("Parent")
        os.close(r)
        os.close(r2)
        pipe1 = b"Pipe1 read"
        pipe2 = b"Pipe2 read"
        os.write(w, pipe1)
        os.write(w2, pipe2)
        
    if pid2 == 0:
        print("Child2")
        os.close(w2)
        r2 = os.fdopen(r2)
        print(r2.read())
        
        
        
if pid == 0:
    pid3=os.fork()
    os.close(w)
    r = os.fdopen(r)
    print(r.read())
    if pid3 != 0:
        
        os.close(r3)
        print("Child1")
        pipe3 = b"Pipe3 read"
        os.write(w3, pipe3)
        
        
    if pid3 == 0:
        print("Child from Child")
        os.close(w3)
        r3 = os.fdopen(r3)
        print(r3.read())

Output:

Parent
Child2
Child1
Child from Child
Pipe2 read
Pipe3 read

The other version would be:

import os
import random



pid = os.fork()

r, w = os.pipe()
r2, w2 = os.pipe()
r3, w3 = os.pipe()

if pid != 0:

    pid2 = os.fork()

    if pid2 != 0:
        print("Parent")
        os.close(r)
        os.close(r2)
        pipe1 = b"Pipe1 read"
        pipe2 = b"Pipe2 read"
        os.write(w, pipe1)
        os.write(w2, pipe2)

    if pid2 == 0:
        print("Child2")
        os.close(w2)
        r2 = os.fdopen(r2)
        print(r2.read())

#Only changed the order here!
if pid == 0:
    pid3 = os.fork()
    if pid3 != 0:
        os.close(w)
        r = os.fdopen(r)
        print(r.read())
        os.close(r3)
        print("Child1")
        pipe3 = b"Pipe3 read"
        os.write(w3, pipe3)

    if pid3 == 0:
        print("Child from Child")
        os.close(w3)
        r3 = os.fdopen(r3)
        print(r3.read())

Output:

Parent
Child2
Child from Child
Pipe2 read

In the second version the third pipe also seems to disappear or break Child1. Could someone please explain me where my problem is and how I connect a pipe correctly from Parent to Child1 (and from Partent to Child2 at the same time).

Thanks in advance!

CodePudding user response:

In the first one, you should setup the first pipe r, w = os.pipe() before you fork. Otherwise you end up with Child1 reading from a different pipe than what Parent is writing to.

In the second one, you need to close the all the extra pipes in the children with (pid==0). That is: Move r3, w3 = os.pipe() to after pid==0, move os.close(w) to before pid3!=0, and add os.close(r) in pid3==0. Then everything should work properly.

Fixed version:

import os
import random



r, w = os.pipe()
pid = os.fork()

r2, w2 = os.pipe()

if pid != 0:

    pid2 = os.fork()

    if pid2 != 0:
        print("Parent")
        os.close(r)
        os.close(r2)
        pipe1 = b"Pipe1 read"
        pipe2 = b"Pipe2 read"
        os.write(w, pipe1)
        os.write(w2, pipe2)

    if pid2 == 0:
        print("Child2")
        os.close(w2)
        r2 = os.fdopen(r2)
        print(r2.read())

#Only changed the order here!
if pid == 0:
    r3, w3 = os.pipe()
    os.close(w)
    pid3 = os.fork()
    if pid3 != 0:
        r = os.fdopen(r)
        print(r.read())
        os.close(r3)
        print("Child1")
        pipe3 = b"Pipe3 read"
        os.write(w3, pipe3)

    if pid3 == 0:
        os.close(r)
        print("Child from Child")
        os.close(w3)
        r3 = os.fdopen(r3)
        print(r3.read())
  • Related