8bf9e83eaf
I think the cause of our issues with random failed-to-exec errors is this SIGCHLD handler. When the parent process asks a light process to do a waitpid operation, we now can get EINTR for two reasons. It used to use signals only for implementing timeouts with SIGALRM, but now it appears possible due to the SIGCHLD. This could lead us to report the waitpid as failing---which it looks can have ExecFuture thinking running==false and reading the exit code as -1. Also, now that we have a SIGCHLD handler (are we sure we want to keep this?), using waitpid() without an EINTR loop is probably similarly broken in the parent process. (Also, isn't it basically incorrect to use wait functions without an EINTR loop in general, though?) I didn't add an EINTR loop in do_waitpid in this diff because it's using signals for timeout (it really should be checking a volatile sigatomic_t that gets set by the handler, though) Also, this means using Process::Exec is suspect in general. All uses looked like debugger or tests only (and when hphpc runs hhvm in a subprocess), so I didn't nuke them (yet). I deleted some random network.h dead code that uses it, though.
97 linhas
3.1 KiB
C++
97 linhas
3.1 KiB
C++
/*
|
|
+----------------------------------------------------------------------+
|
|
| HipHop for PHP |
|
|
+----------------------------------------------------------------------+
|
|
| Copyright (c) 2010- Facebook, Inc. (http://www.facebook.com) |
|
|
+----------------------------------------------------------------------+
|
|
| This source file is subject to version 3.01 of the PHP license, |
|
|
| that is bundled with this package in the file LICENSE, and is |
|
|
| available through the world-wide-web at the following url: |
|
|
| http://www.php.net/license/3_01.txt |
|
|
| If you did not receive a copy of the PHP license and are unable to |
|
|
| obtain it through the world-wide-web, please send a note to |
|
|
| license@php.net so we can mail you a copy immediately. |
|
|
+----------------------------------------------------------------------+
|
|
*/
|
|
|
|
#include "network.h"
|
|
#include "lock.h"
|
|
#include "process.h"
|
|
#include "util.h"
|
|
|
|
#include <netinet/in.h>
|
|
#include <arpa/nameser.h>
|
|
#include <resolv.h>
|
|
|
|
namespace HPHP {
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// without calling res_init(), any call to getaddrinfo() may leak memory:
|
|
// http://sources.redhat.com/ml/libc-hacker/2004-02/msg00049.html
|
|
|
|
class ResolverLibInitializer {
|
|
public:
|
|
ResolverLibInitializer() {
|
|
res_init();
|
|
// We call sethostent with stayopen = 1 to keep /etc/hosts open across calls
|
|
// to prevent mmap contention inside the kernel. Two calls are necessary to
|
|
// properly initialize the stayopen flag in glibc.
|
|
sethostent(1);
|
|
sethostent(1);
|
|
}
|
|
};
|
|
static ResolverLibInitializer _resolver_lib_initializer;
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// thread-safe network functions
|
|
|
|
std::string Util::safe_inet_ntoa(struct in_addr &in) {
|
|
char buf[256];
|
|
memset(buf, 0, sizeof(buf));
|
|
inet_ntop(AF_INET, &in, buf, sizeof(buf)-1);
|
|
return buf;
|
|
}
|
|
|
|
bool Util::safe_gethostbyname(const char *address, HostEnt &result) {
|
|
#if defined(__APPLE__)
|
|
struct hostent *hp = gethostbyname(address);
|
|
|
|
if (!hp) {
|
|
return false;
|
|
}
|
|
|
|
result.hostbuf = *hp;
|
|
freehostent(hp);
|
|
return true;
|
|
#else
|
|
struct hostent *hp;
|
|
int res;
|
|
|
|
size_t hstbuflen = 1024;
|
|
result.tmphstbuf = (char*)malloc(hstbuflen);
|
|
while ((res = gethostbyname_r(address, &result.hostbuf, result.tmphstbuf,
|
|
hstbuflen, &hp, &result.herr)) == ERANGE) {
|
|
hstbuflen *= 2;
|
|
result.tmphstbuf = (char*)realloc(result.tmphstbuf, hstbuflen);
|
|
}
|
|
return !res && hp;
|
|
#endif
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
std::string Util::GetPrimaryIP() {
|
|
struct utsname buf;
|
|
uname((struct utsname *)&buf);
|
|
|
|
HostEnt result;
|
|
if (!safe_gethostbyname(buf.nodename, result)) {
|
|
return buf.nodename;
|
|
}
|
|
|
|
struct in_addr in;
|
|
memcpy(&in.s_addr, *(result.hostbuf.h_addr_list), sizeof(in.s_addr));
|
|
return safe_inet_ntoa(in);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
}
|