Reputation: 148
I'm trying to send data from a C program to a python program (both are running simultaneously). I'm attempting to use the popen function in C. The way I understand it, whatever I write to the file descriptor in C can be read from stdin in the python program. However, the python program appears to hang at the point where it reads from stdin. Any suggestions?
Here's the C program:
test.c
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(void) {
FILE * fp = popen("sudo python display.py", "w");
if (fp == NULL) {
printf("popen error\n");
exit(1);
}
int inc = 0;
char buf[10];
while(1) {
sprintf(buf, "%d", inc);
fputs(buf, fp);
inc++;
sleep(1);
}
return (0);
}
Here is the python program, which should read the value of "inc" and output it
display.py
import sys
value = 0
while(True):
value = sys.stdin.read()
print value
The program seems to hang at value = sys.stdin.read(). I have tried readline() and readlines() as well with the same result.
Upvotes: 3
Views: 2026
Reputation: 1
You rather should use fprintf(3) instead of mixing sprintf
(which is unsafe, prefer snprintf(3)) with fputs
.
You really want to output whole lines (because textual protocols are so convenient to debug). And use readline
on the Python side.
At last, a FILE*
obtained by popen(3) is not even guaranteed to be line-buffered (but could have a much larger buffer, perhaps 4Kbytes or more). You might set its buffer using setvbuf(3) but you really should flush explicitly the FILE*
buffer with fflush(3). If you don't, the output could stay in the buffer for a long time (without any actual write(2) done by stdio
functions like fprintf
or fputs
) so the pipe(7) stays empty.
(so you have problems even on the C side)
The program seems to hang at value = sys.stdin.read().
I guess that not a single byte was actually written by your C code (you could check by using strace(1)) because your fputs
stayed in the buffer. You might need to wait a long time (perhaps 1000 seconds, to fill a buffer of a few kilobytes) to have it actually write something on the pipe, because you forgot the fflush
.
A popen
-ed file should absolutely be pclose
d.
So you should replace your (incorrect) while
loop with:
while(1) {
fprintf(fp, "%d\n", inc);
inc++;
fflush(fp);
sleep(1);
}
And your loop should be exited somehow. Perhaps you might catch some signal(7) -probably SIGTERM
- (but be sure to read signal-safety(7)). Be sure to pclose
(to avoid zombie processes).
(I am assuming you are on Linux or some other POSIX system)
Upvotes: 3
Reputation: 304127
readline()
would work if you were outputting lines from your C program.
Since you never print a newline, readline
will wait forever.
read()
with no parameters will wait until the C program exits (or otherwise closes stdout). Again this is never going to happen with your program
Upvotes: 4