We have downloaded the PHP source code and this is what we have discovered.
First, we need to know what generates the error 'Unable to fork'. It's here:
php-4.3.6/ext/standard/exec.c
#ifdef PHP_WIN32
fp = VCWD_POPEN(d, "rb");
#else
fp = VCWD_POPEN(d, "r");
#endif
if (!fp) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to fork [%s]", d);
efree(d);
efree(buf);
#if PHP_SIGCHILD
signal (SIGCHLD, sig_handler);
#endif
return -1;
}
Now we know that when fd is NULL, you get the error.
fp = VCWD_POPEN(d, "r");
We need to know what VCWD_POPEN is. It is defined here:
php-4.3.6/TSRM/tsrm_virtual_cwd.h
#define VCWD_POPEN(command, type) virtual_popen(command, type TSRMLS_CC)
Then, what is virtual_popen?
php-4.3.6/TSRM/tsrm_virtual_cwd.c
#else /* Unix */
CWD_API FILE *virtual_popen(const char *command, const char *type TSRMLS_DC)
{
int command_length;
char *command_line;
char *ptr;
FILE *retval;
command_length = strlen(command);
ptr = command_line = (char *) malloc(command_length + sizeof("cd ; ") + CWDG(cwd).cwd_length+1);
if (!command_line) {
return NULL;
}
memcpy(ptr, "cd ", sizeof("cd ")-1);
ptr += sizeof("cd ")-1;
if (CWDG(cwd).cwd_length == 0) {
*ptr++ = DEFAULT_SLASH;
} else {
memcpy(ptr, CWDG(cwd).cwd, CWDG(cwd).cwd_length);
ptr += CWDG(cwd).cwd_length;
}
*ptr++ = ' ';
*ptr++ = ';';
*ptr++ = ' ';
memcpy(ptr, command, command_length+1);
retval = popen(command_line, type); <------------
free(command_line);
return retval;
}
Now we know PHP uses popen(). When popen() returns NULL, you get the problem.
Just like fopen(), popen is a standard C IO function.
#include <stdio.h>
FILE *popen(const char *command, const char *mode);
fopen and popen are of data type (structure) FILE which is an unsigned char, i.e. it has a range of 0-255. That's why you get the problem when there are more than 256 open file descriptors.
This problem is mentioned on this web page:
http://www.thetaphi.de/php-ressources/
which you already found last week.
Despite what it says, it is not a bug in Solaris. Solaris just complies with the standard.
The PHP application should have used the UNIX system call function - open() instead.
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *path, int oflag, /* mode_t mode */...);
As you can see the open() function returns an int rather than char, so the 256 limit does not apply to it.
Unless someone is going to change the code in PHP, I think you need to use the CGI workaround provided on that web page.
Bookmarks