__lvalProxy needs to be request local

But it was recently made thread local. If the value left
in it at the end of one request was smart allocated, the
next request would try to free it - but after its already
been swept.

We could make this RequestLocal, but that seems to add even
more overhead. We could probably make it a __thread TypedValue,
and just set it to uninit at the start of each request (and then
tvAsVariant() where its used). This just puts it back to how
it was, since global_variables() is already being dealt with
appropriately.
Esse commit está contido em:
mwilliams
2013-03-27 20:00:07 -07:00
commit de Sara Golemon
commit 4976bf8379
5 arquivos alterados com 82 adições e 39 exclusões
+2 -4
Ver Arquivo
@@ -2257,8 +2257,6 @@ public:
static const bool CheckParams = true;
};
DECLARE_THREAD_LOCAL(Variant, __lvalProxy);
template<typename T>
Variant& Variant::LvalAtImpl0(
Variant *self, T key, Variant *tmp, bool blackHole, ACCESSPARAMS_IMPL) {
@@ -2304,7 +2302,7 @@ head:
*tmp = self->getArrayAccess()->offsetGet(key);
return *tmp;
}
Variant& retv = *(__lvalProxy.get());
Variant& retv = get_global_variables()->__lvalProxy;
retv = self->getArrayAccess()->offsetGet(key);
return retv;
}
@@ -2430,7 +2428,7 @@ Variant &Variant::lvalInvalid() {
}
Variant &Variant::lvalBlackHole() {
Variant &bh = *(__lvalProxy.get());
Variant &bh = get_global_variables()->__lvalProxy;
bh.unset();
return bh;
}
+1
Ver Arquivo
@@ -165,6 +165,7 @@ class GlobalNameValueTableWrapper : public NameValueTableWrapper {
Variant gvm_http_response_header;
Variant __realPropProxy;
Variant __lvalProxy;
Variant stgv_Variant[1];
#define k_SID stgv_Variant[0]
+1 -1
Ver Arquivo
@@ -6,7 +6,7 @@ Log {
Server {
Port = 8080
SourceRoot != echo $(pwd)/runtime/tmp
ThreadCount = 1
AllowedFiles {
0 = string
}
+55 -33
Ver Arquivo
@@ -45,8 +45,9 @@ static int s_admin_port = 0;
static int s_rpc_port = 0;
static int inherit_fd = -1;
bool TestServer::VerifyServerResponse(const char *input, const char *output,
const char *url, const char *method,
bool TestServer::VerifyServerResponse(const char *input, const char **outputs,
const char **urls, int nUrls,
const char *method,
const char *header, const char *postdata,
bool responseHeader,
const char *file /* = "" */,
@@ -70,44 +71,54 @@ bool TestServer::VerifyServerResponse(const char *input, const char *output,
AsyncFunc<TestServer> func(this, &TestServer::RunServer);
func.start();
String server = "http://";
server += f_php_uname("n");
server += ":" + lexical_cast<string>(port) + "/";
server += url;
string actual, err;
for (int i = 0; i < 10; i++) {
Variant c = f_curl_init();
f_curl_setopt(c, k_CURLOPT_URL, server);
f_curl_setopt(c, k_CURLOPT_RETURNTRANSFER, true);
if (postdata) {
f_curl_setopt(c, k_CURLOPT_POSTFIELDS, postdata);
f_curl_setopt(c, k_CURLOPT_POST, true);
}
if (header) {
f_curl_setopt(c, k_CURLOPT_HTTPHEADER, CREATE_VECTOR1(header));
}
if (responseHeader) {
f_curl_setopt(c, k_CURLOPT_HEADER, 1);
}
bool passed = true;
Variant res = f_curl_exec(c);
if (!same(res, false)) {
actual = res.toString();
break;
string actual;
int url = 0;
for (url = 0; url < nUrls; url++) {
String server = "http://";
server += f_php_uname("n");
server += ":" + lexical_cast<string>(port) + "/";
server += urls[url];
actual = "<No response from server>";
string err;
for (int i = 0; i < 10; i++) {
Variant c = f_curl_init();
f_curl_setopt(c, k_CURLOPT_URL, server);
f_curl_setopt(c, k_CURLOPT_RETURNTRANSFER, true);
if (postdata) {
f_curl_setopt(c, k_CURLOPT_POSTFIELDS, postdata);
f_curl_setopt(c, k_CURLOPT_POST, true);
}
if (header) {
f_curl_setopt(c, k_CURLOPT_HTTPHEADER, CREATE_VECTOR1(header));
}
if (responseHeader) {
f_curl_setopt(c, k_CURLOPT_HEADER, 1);
}
Variant res = f_curl_exec(c);
if (!same(res, false)) {
actual = res.toString();
break;
}
sleep(1); // wait until HTTP server is up and running
}
if (actual != outputs[url]) {
if (!responseHeader ||
actual.find(outputs[url]) == string::npos) {
passed = false;
break;
}
}
sleep(1); // wait until HTTP server is up and running
}
AsyncFunc<TestServer>(this, &TestServer::StopServer).run();
func.waitForEnd();
bool passed = (actual == output);
if (responseHeader) {
passed = (actual.find(output) != string::npos);
}
if (!passed) {
printf("%s:%d\nParsing: [%s]\nBet %d:\n"
printf("%s:%d\nParsing: [%s] (req %d)\nBet %d:\n"
"--------------------------------------\n"
"%s"
"--------------------------------------\n"
@@ -115,7 +126,7 @@ bool TestServer::VerifyServerResponse(const char *input, const char *output,
"--------------------------------------\n"
"%s"
"--------------------------------------\n",
file, line, input, (int)strlen(output), output,
file, line, input, url + 1, (int)strlen(outputs[url]), outputs[url],
(int)actual.length(), actual.c_str());
return false;
}
@@ -204,6 +215,7 @@ bool TestServer::RunTests(const std::string &which) {
RUN_TEST(TestInheritFdServer);
RUN_TEST(TestSanity);
RUN_TEST(TestServerVariables);
RUN_TEST(TestInteraction);
RUN_TEST(TestGet);
RUN_TEST(TestPost);
RUN_TEST(TestCookie);
@@ -274,6 +286,16 @@ bool TestServer::TestServerVariables() {
return true;
}
bool TestServer::TestInteraction() {
// run this twice to test lvalBlackHole
VSR2("<?php "
"$a[] = new stdclass;"
"var_dump(count(array_combine($a, $a)));",
"int(0)\n");
return true;
}
bool TestServer::TestGet() {
VSGET("<?php var_dump($_GET['name']);",
"string(0) \"\"\n", "string?name");
+23 -1
Ver Arquivo
@@ -36,6 +36,8 @@ public:
// test $_ variables
bool TestServerVariables();
// test things that need more than one request
bool TestInteraction();
bool TestGet();
bool TestPost();
bool TestCookie();
@@ -71,6 +73,17 @@ protected:
const char *header, const char *postdata,
bool responseHeader,
const char *file = "", int line = 0,
int port = 0) {
return VerifyServerResponse(input, &output, &url, 1,
method, header, postdata, responseHeader,
file, line, port);
}
bool VerifyServerResponse(const char *input, const char **outputs,
const char **urls, int nUrl, const char *method,
const char *header, const char *postdata,
bool responseHeader,
const char *file = "", int line = 0,
int port = 0);
bool PreBindSocket();
void CleanupPreBoundSocket();
@@ -81,9 +94,18 @@ protected:
#define VSR(input, output) \
if (!Count(VerifyServerResponse(input, output, "string", "GET", nullptr, \
nullptr, false, __FILE__,__LINE__))) \
nullptr, false, __FILE__,__LINE__))) \
return false;
#define VSR2(input, output) do { \
const char* urls[2] = { "string", "string" }; \
const char* outputs[2] = { output, output }; \
if (!Count(VerifyServerResponse(input, outputs, urls, 2, "GET", \
nullptr, nullptr, false, \
__FILE__,__LINE__))) \
return false; \
} while (false)
#define VSRES(input, output) \
if (!Count(VerifyServerResponse(input, output, "string", "GET", nullptr, \
nullptr, true, __FILE__,__LINE__))) \