Blog
PHP system() calls result in CGI Error on IIS
Writing a custom executable for a client earlier this month, I encountered an issue with calling it from within a PHP script on IIS running PHP 5.2. Every time the page was accessed, we would get an error page saying something along the lines of "The CGI application did not return a complete set of headers". This is of no help to anyone and since it was coming up on a remotely hosted server I had no real way to check the logs or investigate easily. While trolling along on Google, I managed to locate references to the exact problem in the PHP bug list. In a series of comments, the problem is eventually solved by piecing together bits of information from a couple of users. To clarify: this is not a PHP bug, it is an IIS bug. The knowledgebase article for IIS is here. It is suggested that a patch to fix the issue has been released but for those of us who share hosting, the luxury of applying patches does not exist (and nor should it). Fortunately, there is a simple workaround, kindly hinted at but not completely correctly stated by dan at hostway dot nl in the bug's comment posts.
He's right - returning a MIME header will fix the problem - but not completely right. You can return any header or none at all if you like, since PHP automatically generates most of the headers for you. What you actually need to do is make sure that before you make the call to "system", "shell_exec" or "`" (backtick operator) you must flush at least some of the final output of the page. The problem seems to be that executing an external command takes too long and since PHP has not yet returned anything to IIS, IIS assumes that it is broken and cuts off its execution, displaying the error I mentioned. Another user on the bug discussion also suggests that it only becomes an issue when the execution of the command fails (i.e. access denied, invalid command), but I have found that this is not the case. So, to fix the probem, all you really need to do is call flush before issuing the system command, as shown in this example:
header("Content-Type: text/html");
flush();
// Any system calls can be made below this point without problems
// (these are just examples)
system(`tasklist | find "IIS"`);
`tasklist | find "PHP"`;
shell_exec("dir");
?>
Its as simple as that. Just make sure that some output has been recieved by IIS before you start an intensive process like a system call and there should be no issues. You can then execute the program and show its output later. The only thing you can't do is redirect after this, since the headers will have already been sent. Rememer: just making a call to header won't always work, since PHPs internal buffering may result in the headers being held onto. To be sure, always explicitly call flush.
Link to this article |
Make a Comment
Tags:
IIS, Windows Server, WIMP, PHP, Errors, Bugs, Hacks






