Skip to content
Advertisement

Reading from STDIN pipe when using proc_open

I am trying to make a website where people can compile and run their code online, thus we need to find an interactive way for users to send instructions.

Actually, what first comes to mind is exec() or system(), but when users want to input sth, this way won’t work. So we have to use proc_open().

For instance, the following code

JavaScript

When I used proc_open(), like this

JavaScript

When running the C code, I want to get the first STDOUT stream, and input the number, then get the second STDOUT stream. But if I have the commented line uncommented, the page will be blocked.

Is there a way to solve the problem? How can I read from the pipe while not all data has been put there? Or is there a better way to write this kind of interactive program?

Advertisement

Answer

It is more a C or a glibc problem. You’ll have to use fflush(stdout).

Why? And what’s the difference between running a.out in a terminal and calling it from PHP?

Answer: If you run a.out in a terminal (being stdin a tty) then the glibc will use line buffered IO. But if you run it from another program (PHP in this case) and it’s stdin is a pipe (or whatever but not a tty) than the glibc will use internal IO buffering. That’s why the first fgets() blocks if uncommented. For more info check this article.

Good news: You can control this buffering using the stdbuf command. Change $run_string to:

JavaScript

Here comes a working example. Working even if the C code don’t cares about fflush() as it is using the stdbuf command:

Starting subprocess

JavaScript

set all streams to non blocking mode

JavaScript

get child pid. we need it later

JavaScript

poll until child terminates

JavaScript
User contributions licensed under: CC BY-SA
9 People found this is helpful
Advertisement