ftiaronsem
ftiaronsem

Reputation: 1584

python - subprocess call not terminating when using pipes

I have a strange issue with python 2.6.5. If I call

p = subprocess.Popen(["ifup eth0"], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = p.communicate()

with the interface eth0 being down, the python programm hangs. "p.communicate()" takes a minute or longer to finish. If the interface is up before, the programm runs smoothly. I tested "ifup eth0" from the command line manually for both cases and its lightning fast.

If you have any idea what the Problem might be, I would appreciate it very much.

Thanks in advance

EDIT:

Based on the answers, I tried the following things:

p = subprocess.Popen(["ifup", "eth0"], shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = p.communicate()

If the interface was up before, the skript runs smoothly. However if the interface was down, python hangs again. I also tried:

p = subprocess.Popen(["ifup", "eth0"], shell=False)
out, err = p.communicate()

And EVERYTHING runs perfektly fast. Therefore it might be indeed related to a deadlock, as pointed out funktku. However the python documentation also says python ref:

Warning

This will deadlock when using stdout=PIPE and/or stderr=PIPE and the child process generates enough output to a pipe such that it blocks waiting for the OS pipe buffer to accept more data. Use communicate() to avoid that.

Therefore there shouldn't be a deadlock. Hmm... Here is the detailed output when I run the programms on the command line:

1 Case, interface eth0 already up:

ifup eth0
Interface eth0 already configured

2 Case, interface down before:

ifup eth0 
ssh stop/waiting
ssh start/running

So the ifup command generates two lines of ouput in case the interface is down before and one line of ouput otherwise. This is the only difference I noticed. But I doubt this is the cause of the problem, since "ls -ahl" causes many more lines of ouput and is running very well.

I also tried playing around with the buffersize argument, however no success, by setting it to some large value like 4096.

Do you have an ideas, what might be the cause of that? Or is this probably a bug in python Pipe handling or the ifup command itself? Do I really have to use the old os.popen(cmd).read()????

EDIT2:

os.popen(cmd).read() suffers from the same problem. Any idea of how I can test the pipe behaviour of ifup on the commandline?

I appreciate every hint, thanks in advance

Upvotes: 2

Views: 4489

Answers (3)

Denis Moskalets
Denis Moskalets

Reputation: 56

/etc/network/if-up.d/ntpdate does not detach correctly

That's why read() waits until fds (stdin/stdout/stderr) are closed. You can detach stdin/stderr/stdout (do not add stdout=subprocess.PIPE and the same to Popen constructor call).

Upvotes: 1

user225312
user225312

Reputation: 131677

p = subprocess.Popen(["ifup", "eth0"], shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = p.communicate()

Set shell=False, you don't need it.

Try running this code, it should work. Notice how two arguments are separate elements in the list.

Upvotes: 1

Utku Zihnioglu
Utku Zihnioglu

Reputation: 4873

You should check out the warning under the subprocess.call method. It might be the reason of your problem.

Warning

Like Popen.wait(), this will deadlock when using stdout=PIPE and/or stderr=PIPE and the child process generates enough output to a pipe such that it blocks waiting for the OS pipe buffer to accept more data.

Upvotes: 3

Related Questions