Alternate fix for RDS profiling bug
[hiphop-php.git] / hphp / runtime / base / runtime-option.cpp
blobcbb1f5a6e8955c812935b88339b13c9953ee456a
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
17 #include "hphp/runtime/base/runtime-option.h"
19 #include "hphp/parser/scanner.h"
20 #include "hphp/runtime/base/autoload-handler.h"
21 #include "hphp/runtime/base/bespoke-array.h"
22 #include "hphp/runtime/base/builtin-functions.h"
23 #include "hphp/runtime/base/coeffects-config.h"
24 #include "hphp/runtime/base/config.h"
25 #include "hphp/runtime/base/crash-reporter.h"
26 #include "hphp/runtime/base/execution-context.h"
27 #include "hphp/runtime/base/extended-logger.h"
28 #include "hphp/runtime/base/file-util-defs.h"
29 #include "hphp/runtime/base/file-util.h"
30 #include "hphp/runtime/base/hphp-system.h"
31 #include "hphp/runtime/base/ini-setting.h"
32 #include "hphp/runtime/base/init-fini-node.h"
33 #include "hphp/runtime/base/memory-manager.h"
34 #include "hphp/runtime/base/plain-file.h"
35 #include "hphp/runtime/base/rds.h"
36 #include "hphp/runtime/base/request-info.h"
37 #include "hphp/runtime/base/static-string-table.h"
38 #include "hphp/runtime/base/tv-refcount.h"
39 #include "hphp/runtime/base/zend-string.h"
40 #include "hphp/runtime/base/zend-url.h"
41 #include "hphp/runtime/ext/extension-registry.h"
42 #include "hphp/runtime/server/access-log.h"
43 #include "hphp/runtime/server/cli-server.h"
44 #include "hphp/runtime/server/files-match.h"
45 #include "hphp/runtime/server/satellite-server.h"
46 #include "hphp/runtime/server/virtual-host.h"
47 #include "hphp/runtime/vm/jit/code-cache.h"
48 #include "hphp/runtime/vm/jit/mcgen-translate.h"
49 #include "hphp/runtime/vm/treadmill.h"
50 #include "hphp/util/arch.h"
51 #include "hphp/util/atomic-vector.h"
52 #include "hphp/util/build-info.h"
53 #include "hphp/util/bump-mapper.h"
54 #include "hphp/util/cpuid.h"
55 #include "hphp/util/current-executable.h" // @donotremove
56 #include "hphp/util/file-cache.h"
57 #include "hphp/util/gzip.h"
58 #include "hphp/util/hardware-counter.h"
59 #include "hphp/util/hdf.h"
60 #include "hphp/util/light-process.h"
61 #include "hphp/util/log-file-flusher.h"
62 #include "hphp/util/logger.h"
63 #include "hphp/util/network.h"
64 #include "hphp/util/numa.h"
65 #include "hphp/util/process.h"
66 #include "hphp/util/service-data.h"
67 #include "hphp/util/stack-trace.h"
68 #include "hphp/util/text-util.h"
69 #include "hphp/util/zstd.h"
70 #include "hphp/zend/zend-string.h"
72 #include <cstdint>
73 #include <limits>
74 #include <map>
75 #include <memory>
76 #include <set>
77 #include <stdexcept>
78 #include <vector>
80 #include <boost/algorithm/string/predicate.hpp>
81 #include <folly/CPortability.h>
82 #include <folly/Conv.h>
83 #include <folly/DynamicConverter.h>
84 #include <folly/FileUtil.h>
85 #include <folly/String.h>
86 #include <folly/portability/SysResource.h>
87 #include <folly/portability/SysTime.h>
88 #include <folly/portability/Unistd.h>
90 #if defined (__linux__) && defined (__aarch64__)
91 #include <sys/auxv.h>
92 #include <asm/hwcap.h>
93 #endif
95 #ifdef __APPLE__
96 #define st_mtim st_mtimespec
97 #define st_ctim st_ctimespec
98 #endif
100 namespace HPHP {
101 ///////////////////////////////////////////////////////////////////////////////
103 bool RepoOptions::s_init{false};
104 RepoOptions RepoOptions::s_defaults;
106 namespace {
108 #ifdef FACEBOOK
109 const static bool s_PHP7_default = false;
110 #else
111 const static bool s_PHP7_default = true;
112 #endif
113 // PHP7 is off by default (false). s_PHP7_master is not a static member of
114 // RuntimeOption so that it's private to this file and not exposed -- it's a
115 // master switch only, and not to be used for any actual gating, use the more
116 // granular options instead. (It can't be a local since Config::Bind will take
117 // and store a pointer to it.)
118 static bool s_PHP7_master = s_PHP7_default;
120 std::vector<std::string> s_RelativeConfigs;
122 ////////////////////////////////////////////////////////////////////////////////
124 void mangleForKey(bool b, std::string& s) { s += (b ? '1' : '0'); }
125 void mangleForKey(const RepoOptions::StringMap& map, std::string& s) {
126 s += folly::to<std::string>(map.size());
127 s += '\0';
128 for (auto const& par : map) {
129 s += par.first;
130 s += '\0';
131 s += par.second;
132 s += '\0';
135 void mangleForKey(const RepoOptions::StringVector& vec, std::string& s) {
136 s += folly::to<std::string>(vec.size());
137 s += '\0';
138 for (auto const& val : vec) {
139 s += val;
140 s += '\0';
143 void mangleForKey(const std::string& s1, std::string& s2) { s2 += s1; }
144 void hdfExtract(const Hdf& hdf, const char* name, bool& val, bool dv) {
145 val = hdf[name].configGetBool(dv);
147 void hdfExtract(const Hdf& hdf, const char* name, uint16_t& val, uint16_t dv) {
148 val = hdf[name].configGetUInt16(dv);
150 void hdfExtract(
151 const Hdf& hdf,
152 const char* name,
153 RepoOptions::StringMap& map,
154 const RepoOptions::StringMap& dv
156 Hdf config = hdf[name];
157 if (config.exists() && !config.isEmpty()) config.configGet(map);
158 else map = dv;
160 void hdfExtract(
161 const Hdf& hdf,
162 const char* name,
163 RepoOptions::StringVector& vec,
164 const RepoOptions::StringVector& dv
166 Hdf config = hdf[name];
167 if (config.exists() && !config.isEmpty()) config.configGet(vec);
168 else vec = dv;
170 void hdfExtract(
171 const Hdf& hdf,
172 const char* name,
173 std::string& val,
174 std::string dv
176 val = hdf[name].configGetString(dv);
178 folly::dynamic toIniValue(bool b) {
179 return b ? "1" : "0";
182 folly::dynamic toIniValue(const RepoOptions::StringMap& map) {
183 folly::dynamic obj = folly::dynamic::object();
184 for (auto& kv : map) {
185 obj[kv.first] = kv.second;
187 return obj;
190 folly::dynamic toIniValue(const RepoOptions::StringVector& vec) {
191 folly::dynamic obj = folly::dynamic::array();
192 for (auto& val : vec) {
193 obj.push_back(val);
195 return obj;
198 folly::dynamic toIniValue(const std::string& str) {
199 return str;
202 struct CachedRepoOptions {
203 CachedRepoOptions() = default;
204 explicit CachedRepoOptions(RepoOptions&& opts)
205 : options(new RepoOptions(std::move(opts)))
207 CachedRepoOptions(const CachedRepoOptions& opts)
208 : options(nullptr)
210 if (auto o = opts.options.load(std::memory_order_relaxed)) {
211 options.store(new RepoOptions(*o), std::memory_order_relaxed);
214 ~CachedRepoOptions() {
215 Treadmill::enqueue([opt = options.exchange(nullptr)] { delete opt; });
218 CachedRepoOptions& operator=(const CachedRepoOptions& opts) {
219 auto const o = opts.options.load(std::memory_order_relaxed);
220 auto const old = options.exchange(o ? new RepoOptions(*o) : nullptr);
221 if (old) Treadmill::enqueue([old] { delete old; });
222 return *this;
225 static bool isChanged(const RepoOptions* opts, struct stat s) {
226 auto const o = opts->stat();
227 return
228 s.st_mtim.tv_sec != o.st_mtim.tv_sec ||
229 s.st_mtim.tv_nsec != o.st_mtim.tv_nsec ||
230 s.st_ctim.tv_sec != o.st_ctim.tv_sec ||
231 s.st_ctim.tv_nsec != o.st_ctim.tv_nsec ||
232 s.st_dev != o.st_dev ||
233 s.st_ino != o.st_ino;
236 const RepoOptions* update(RepoOptions&& opts) const {
237 auto const val = new RepoOptions(std::move(opts));
238 auto const old = options.exchange(val);
239 if (old) Treadmill::enqueue([old] { delete old; });
240 return val;
243 const RepoOptions* fetch(struct stat st) const {
244 auto const opts = options.load(std::memory_order_relaxed);
245 return opts && !isChanged(opts, st) ? opts : nullptr;
248 mutable std::atomic<RepoOptions*> options{nullptr};
251 struct RepoOptionCacheKey {
252 bool wrapped;
253 std::string filename;
255 struct RepoOptionCacheKeyCompare {
256 bool equal(const RepoOptionCacheKey& k1, const RepoOptionCacheKey& k2) const {
257 return k1.wrapped == k2.wrapped && k1.filename == k2.filename;
259 size_t hash(const RepoOptionCacheKey& k) const {
260 return std::hash<bool>()(k.wrapped) ^
261 hash_string_cs_unsafe(k.filename.c_str(), k.filename.size());
264 using RepoOptionCache = tbb::concurrent_hash_map<
265 RepoOptionCacheKey,
266 CachedRepoOptions,
267 RepoOptionCacheKeyCompare
269 RepoOptionCache s_repoOptionCache;
271 template<class F>
272 bool walkDirTree(std::string fpath, F func) {
273 const char* filename = ".hhvmconfig.hdf";
274 do {
275 auto const off = fpath.rfind('/');
276 if (off == std::string::npos) return false;
277 fpath.resize(off);
278 fpath += '/';
279 fpath += filename;
281 if (func(fpath)) return true;
283 fpath.resize(off);
284 } while (!fpath.empty() && fpath != "/");
285 return false;
288 RDS_LOCAL(std::string, s_lastSeenRepoConfig);
292 ParserEnv RepoOptions::getParserEnvironment() const {
293 return ParserEnv {
294 true // codegen
295 , true // hhvm_compat_mode
296 , true // php5_compat_mode
297 , AllowNewAttributeSyntax
298 , EnableXHPClassModifier
299 , DisableXHPElementMangling
300 , false // disable_xhp_children_declarations
301 , DisallowFunAndClsMethPseudoFuncs
302 , true // interpret_soft_types_as_like_types
306 // Mapping must match HHBCFlags in compile.rs
307 std::uint32_t RepoOptions::getCompilerFlags() const {
308 std::uint32_t hhbc_flags = 0;
310 #define HHBC_FLAGS() \
311 SETFLAGS(LTRAssign, 0) \
312 SETFLAGS(UVS, 1) \
313 SETFLAGS(RuntimeOption::RepoAuthoritative, 4) \
314 SETFLAGS(RuntimeOption::EvalJitEnableRenameFunction, 5) \
315 SETFLAGS(RuntimeOption::EvalLogExternCompilerPerf, 6) \
316 SETFLAGS(RuntimeOption::EnableIntrinsicsExtension, 7) \
317 SETFLAGS(RuntimeOption::DisableNontoplevelDeclarations, 8) \
318 SETFLAGS(RuntimeOption::EvalEmitClsMethPointers, 10) \
319 SETFLAGS(RuntimeOption::EvalEmitMethCallerFuncPointers, 11) \
320 SETFLAGS(RuntimeOption::EvalEnableImplicitContext, 12) \
321 SETFLAGS(RuntimeOption::EvalFoldLazyClassKeys, 15)
323 #define SETFLAGS(flag, n) \
324 if (flag) {hhbc_flags |= 1 << n;}
325 HHBC_FLAGS()
326 #undef SETFLAGS
327 return hhbc_flags;
330 std::string RepoOptions::getAliasedNamespacesConfig() const {
331 folly::dynamic m_config = folly::dynamic::object();
332 m_config["hhvm.aliased_namespaces"] =
333 folly::dynamic::object("global_value", folly::toDynamic(AliasedNamespaces));
334 return folly::toJson(m_config);
337 std::uint32_t RepoOptions::getFactsFlags() const {
338 int32_t flags =
339 1 << 0 | //php5_compat_mode
340 1 << 1 | //hhvm_compat_mode
341 AllowNewAttributeSyntax << 2 |
342 EnableXHPClassModifier << 3 |
343 DisableXHPElementMangling << 4;
344 return flags;
347 std::uint32_t RepoOptions::getDeclFlags() const {
348 int32_t flags =
349 DisableXHPElementMangling << 0 |
350 1 << 1 | // interpret_soft_types_as_like_types
351 AllowNewAttributeSyntax << 2 |
352 EnableXHPClassModifier << 3 |
353 1 << 4 | //php5_compat_mode
354 1 << 5; //hhvm_compat_mode
355 return flags;
358 // Mapping must match ParserFlags in compile.rs
359 std::uint32_t RepoOptions::getParserFlags() const {
360 std::uint32_t parser_flags = 0;
362 #define PARSER_FLAGS() \
363 SETFLAGS(AbstractStaticProps, 0) \
364 SETFLAGS(AllowNewAttributeSyntax, 1) \
365 SETFLAGS(AllowUnstableFeatures, 2) \
366 SETFLAGS(ConstDefaultFuncArgs, 3) \
367 SETFLAGS(ConstStaticProps, 4) \
368 SETFLAGS(DisableArray, 5) \
369 SETFLAGS(DisableArrayCast, 6) \
370 SETFLAGS(DisableArrayTypehint, 7) \
371 SETFLAGS(DisableLvalAsAnExpression, 8) \
372 SETFLAGS(DisableUnsetClassConst, 9) \
373 SETFLAGS(DisallowInstMeth, 10) \
374 SETFLAGS(DisableXHPElementMangling, 11) \
375 SETFLAGS(DisallowFunAndClsMethPseudoFuncs, 12) \
376 SETFLAGS(DisallowFuncPtrsInConstants, 13) \
377 SETFLAGS(EnableEnumClasses,16) \
378 SETFLAGS(EnableXHPClassModifier,17) \
379 SETFLAGS(RuntimeOption::EnableClassLevelWhereClauses, 20) \
380 SETFLAGS(EscapeBrace, 21)
382 #define SETFLAGS(flag, n) \
383 if (flag) {parser_flags |= 1 << n;}
384 PARSER_FLAGS()
385 #undef SETFLAGS
386 return parser_flags;
389 const RepoOptions& RepoOptions::forFile(const char* path) {
390 tracing::BlockNoTrace _{"repo-options"};
392 if (!RuntimeOption::EvalEnablePerRepoOptions) return defaults();
394 std::string fpath{path};
395 if (boost::starts_with(fpath, "/:")) return defaults();
397 // Wrap filesystem accesses if needed to proxy info from cli server client.
398 Stream::Wrapper* wrapper = nullptr;
399 if (get_cli_ucred()) {
400 wrapper = Stream::getWrapperFromURI(path);
401 if (wrapper && !wrapper->isNormalFileStream()) wrapper = nullptr;
403 auto const wrapped_stat = [&](const char* path, struct stat* st) {
404 if (wrapper) return wrapper->stat(path, st);
405 return ::stat(path, st);
408 auto const wrapped_open = [&](const char* path) -> Optional<String> {
409 if (wrapper) {
410 if (auto const file = wrapper->open(path, "r", 0, nullptr)) {
411 return file->read();
413 return std::nullopt;
416 auto const fd = open(path, O_RDONLY);
417 if (fd < 0) return std::nullopt;
418 auto file = req::make<PlainFile>(fd);
419 return file->read();
423 auto const isParentOf = [] (const std::string& p1, const std::string& p2) {
424 return boost::starts_with(
425 boost::filesystem::path{p2},
426 boost::filesystem::path{p1}.parent_path()
430 // Fast path: we have an active request and it has cached a RepoOptions
431 // which has not been modified. This only works when the runtime option
432 // Eval.FatalOnParserOptionMismatch is set. It can cause us to miss out on
433 // configs that were added between the current directory and the source file.
434 // (Loading these configs would result in a fatal anyway with this option)
435 if (!g_context.isNull()) {
436 if (auto const opts = g_context->getRepoOptionsForRequest()) {
437 // If path() is empty we have the default() options, which means we have
438 // negatively cached the existance of a .hhvmconfig.hdf for this request.
439 if (opts->path().empty()) return *opts;
441 if (isParentOf(opts->path(), fpath)) {
442 struct stat st;
443 if (wrapped_stat(opts->path().data(), &st) == 0) {
444 if (!CachedRepoOptions::isChanged(opts, st)) return *opts;
450 auto const set = [&] (
451 RepoOptionCache::const_accessor& rpathAcc,
452 const std::string& path,
453 const struct stat& st
454 ) -> const RepoOptions* {
455 *s_lastSeenRepoConfig = path;
456 if (auto const opts = rpathAcc->second.fetch(st)) {
457 return opts;
459 auto const contents = wrapped_open(path.data());
460 if (!contents) return nullptr;
461 RepoOptions newOpts{ contents->data(), path.data()};
462 newOpts.m_stat = st;
463 return rpathAcc->second.update(std::move(newOpts));
466 auto const test = [&] (const std::string& path) -> const RepoOptions* {
467 struct stat st;
468 RepoOptionCache::const_accessor rpathAcc;
469 const RepoOptionCacheKey key {(bool)wrapper, path};
470 if (!s_repoOptionCache.find(rpathAcc, key)) return nullptr;
471 if (wrapped_stat(path.data(), &st) != 0) {
472 s_repoOptionCache.erase(rpathAcc);
473 return nullptr;
475 return set(rpathAcc, path, st);
478 const RepoOptions* ret{nullptr};
480 // WARNING: when Eval.CachePerRepoOptionsPath we cache the last used path for
481 // RepoOptions per thread, and while we will detect changes to this
482 // file, and do a rescan in the event that it is deleted or doesn't
483 // match the current file being loaded, we will miss out on new
484 // configs that may be added. Since we expect to see a single config
485 // per repository we expect that this will be a reasonably safe,
486 // optimization.
487 if (RuntimeOption::EvalCachePerRepoOptionsPath) {
488 if (!s_lastSeenRepoConfig->empty() &&
489 isParentOf(*s_lastSeenRepoConfig, fpath)) {
490 if (auto const r = test(*s_lastSeenRepoConfig)) return *r;
491 s_lastSeenRepoConfig->clear();
494 // If the last seen path isn't set yet or is no longer accurate try checking
495 // other cached paths before falling back to the filesystem.
496 walkDirTree(fpath, [&] (const std::string& path) {
497 return (ret = test(path)) != nullptr;
501 if (ret) return *ret;
503 walkDirTree(fpath, [&] (const std::string& path) {
504 struct stat st;
505 if (wrapped_stat(path.data(), &st) != 0) return false;
506 RepoOptionCache::const_accessor rpathAcc;
507 const RepoOptionCacheKey key {(bool)wrapper, path};
508 s_repoOptionCache.insert(rpathAcc, key);
509 ret = set(rpathAcc, path, st);
510 return true;
513 return ret ? *ret : defaults();
516 void RepoOptions::calcCacheKey() {
517 std::string raw;
518 #define N(_, n, ...) mangleForKey(n, raw);
519 #define P(_, n, ...) mangleForKey(n, raw);
520 #define H(_, n, ...) mangleForKey(n, raw);
521 #define E(_, n, ...) mangleForKey(n, raw);
522 PARSERFLAGS()
523 AUTOLOADFLAGS()
524 #undef N
525 #undef P
526 #undef H
527 #undef E
528 m_sha1 = SHA1{string_sha1(raw)};
531 std::string RepoOptions::toJSON() const {
532 return folly::toJson(toDynamic());
535 void RepoOptions::calcDynamic() {
536 m_cachedDynamic = folly::dynamic::object();
537 #define OUT(key, var) \
539 auto const ini_name = Config::IniName(key); \
540 auto const ini_value = toIniValue(var); \
541 folly::dynamic entry = folly::dynamic::object(); \
542 entry["global_value"] = ini_value; \
543 entry["local_value"] = ini_value; \
544 entry["access"] = 4; \
545 m_cachedDynamic[ini_name] = entry; \
548 #define N(_, n, ...) OUT(#n, n)
549 #define P(_, n, ...) OUT("PHP7." #n, n)
550 #define H(_, n, ...) OUT("Hack.Lang." #n, n)
551 #define E(_, n, ...) OUT("Eval." #n, n)
552 PARSERFLAGS()
553 AUTOLOADFLAGS();
554 #undef N
555 #undef P
556 #undef H
557 #undef E
559 #undef OUT
562 const RepoOptions& RepoOptions::defaults() {
563 always_assert(s_init);
564 return s_defaults;
567 void RepoOptions::filterNamespaces() {
568 for (auto it = AliasedNamespaces.begin(); it != AliasedNamespaces.end(); ) {
569 if (!is_valid_class_name(it->second)) {
570 Logger::Warning("Skipping invalid AliasedNamespace %s\n",
571 it->second.c_str());
572 it = AliasedNamespaces.erase(it);
573 continue;
576 while (it->second.size() && it->second[0] == '\\') {
577 it->second = it->second.substr(1);
580 ++it;
584 RepoOptions::RepoOptions(const char* str, const char* file) : m_path(file) {
585 always_assert(s_init);
586 Hdf config{};
587 config.fromString(str);
588 Hdf parserConfig = config["Parser"];
590 #define N(_, n, ...) hdfExtract(parserConfig, #n, n, s_defaults.n);
591 #define P(_, n, ...) hdfExtract(parserConfig, "PHP7." #n, n, s_defaults.n);
592 #define H(_, n, ...) hdfExtract(parserConfig, "Hack.Lang." #n, n, s_defaults.n);
593 #define E(_, n, ...) hdfExtract(parserConfig, "Eval." #n, n, s_defaults.n);
594 PARSERFLAGS();
595 #undef N
596 #undef P
597 #undef H
598 #undef E
600 Hdf autoloadConfig = config["Autoload"];
601 #define N(_, n, ...) hdfExtract(autoloadConfig, #n, n, s_defaults.n);
602 #define P(_, n, ...) hdfExtract(autoloadConfig, "PHP7." #n, n, s_defaults.n);
603 #define H(_, n, ...) hdfExtract(autoloadConfig, "Hack.Lang." #n, n, \
604 s_defaults.n);
605 #define E(_, n, ...) hdfExtract(autoloadConfig, "Eval." #n, n, s_defaults.n);
606 AUTOLOADFLAGS();
607 #undef N
608 #undef P
609 #undef H
610 #undef E
612 filterNamespaces();
613 calcCacheKey();
614 calcDynamic();
617 void RepoOptions::initDefaults(const Hdf& hdf, const IniSettingMap& ini) {
618 #define N(_, n, dv) Config::Bind(n, ini, hdf, #n, dv);
619 #define P(_, n, dv) Config::Bind(n, ini, hdf, "PHP7." #n, dv);
620 #define H(_, n, dv) Config::Bind(n, ini, hdf, "Hack.Lang." #n, dv);
621 #define E(_, n, dv) Config::Bind(n, ini, hdf, "Eval." #n, dv);
622 PARSERFLAGS()
623 AUTOLOADFLAGS()
624 #undef N
625 #undef P
626 #undef H
627 #undef E
629 filterNamespaces();
630 m_path.clear();
631 calcCacheKey();
634 void RepoOptions::setDefaults(const Hdf& hdf, const IniSettingMap& ini) {
635 always_assert(!s_init);
636 s_defaults.initDefaults(hdf, ini);
637 s_init = true;
640 ///////////////////////////////////////////////////////////////////////////////
642 std::string RuntimeOption::BuildId;
643 std::string RuntimeOption::InstanceId;
644 std::string RuntimeOption::DeploymentId;
645 int64_t RuntimeOption::ConfigId = 0;
646 std::string RuntimeOption::PidFile = "www.pid";
648 bool RuntimeOption::ServerMode = false;
650 bool RuntimeOption::EnableHipHopSyntax = true;
651 bool RuntimeOption::EnableShortTags = true;
652 bool RuntimeOption::EnableXHP = true;
653 bool RuntimeOption::EnableIntrinsicsExtension = false;
654 bool RuntimeOption::CheckSymLink = true;
655 bool RuntimeOption::TrustAutoloaderPath = false;
656 bool RuntimeOption::EnableArgsInBacktraces = true;
657 bool RuntimeOption::EnableZendIniCompat = true;
658 bool RuntimeOption::TimeoutsUseWallTime = true;
659 bool RuntimeOption::CheckFlushOnUserClose = true;
660 bool RuntimeOption::EvalAuthoritativeMode = false;
661 bool RuntimeOption::DumpPreciseProfData = true;
662 uint32_t RuntimeOption::EvalInitialStaticStringTableSize =
663 kDefaultInitialStaticStringTableSize;
664 uint32_t RuntimeOption::EvalInitialNamedEntityTableSize = 30000;
665 JitSerdesMode RuntimeOption::EvalJitSerdesMode{};
666 int RuntimeOption::ProfDataTTLHours = 24;
667 std::string RuntimeOption::ProfDataTag;
668 std::string RuntimeOption::EvalJitSerdesFile;
670 std::map<std::string, ErrorLogFileData> RuntimeOption::ErrorLogs = {
671 {Logger::DEFAULT, ErrorLogFileData()},
673 // these hold the DEFAULT logger
674 std::string RuntimeOption::LogFile;
675 std::string RuntimeOption::LogFileSymLink;
676 uint16_t RuntimeOption::LogFilePeriodMultiplier;
678 int RuntimeOption::LogHeaderMangle = 0;
679 bool RuntimeOption::AlwaysLogUnhandledExceptions = true;
680 bool RuntimeOption::AlwaysEscapeLog = true;
681 bool RuntimeOption::NoSilencer = false;
682 int RuntimeOption::ErrorUpgradeLevel = 0;
683 bool RuntimeOption::CallUserHandlerOnFatals = false;
684 bool RuntimeOption::ThrowExceptionOnBadMethodCall = true;
685 bool RuntimeOption::LogNativeStackOnOOM = true;
686 int RuntimeOption::RuntimeErrorReportingLevel =
687 static_cast<int>(ErrorMode::HPHP_ALL);
688 int RuntimeOption::ForceErrorReportingLevel = 0;
690 std::string RuntimeOption::ServerUser;
691 std::vector<std::string> RuntimeOption::TzdataSearchPaths;
693 int RuntimeOption::MaxSerializedStringSize = 64 * 1024 * 1024; // 64MB
694 int64_t RuntimeOption::NoticeFrequency = 1;
695 int64_t RuntimeOption::WarningFrequency = 1;
696 int RuntimeOption::RaiseDebuggingFrequency = 1;
697 int64_t RuntimeOption::SerializationSizeLimit = StringData::MaxSize;
699 std::string RuntimeOption::AccessLogDefaultFormat = "%h %l %u %t \"%r\" %>s %b";
700 std::map<std::string, AccessLogFileData> RuntimeOption::AccessLogs;
702 std::string RuntimeOption::AdminLogFormat = "%h %t %s %U";
703 std::string RuntimeOption::AdminLogFile;
704 std::string RuntimeOption::AdminLogSymLink;
706 std::map<std::string, AccessLogFileData> RuntimeOption::RPCLogs;
708 std::string RuntimeOption::Host;
709 std::string RuntimeOption::DefaultServerNameSuffix;
710 std::string RuntimeOption::ServerType = "proxygen";
711 std::string RuntimeOption::ServerIP;
712 std::string RuntimeOption::ServerFileSocket;
713 int RuntimeOption::ServerPort = 80;
714 int RuntimeOption::ServerPortFd = -1;
715 int RuntimeOption::ServerBacklog = 128;
716 int RuntimeOption::ServerConnectionLimit = 0;
717 int RuntimeOption::ServerThreadCount = 50;
718 int RuntimeOption::ServerQueueCount = 50;
719 int RuntimeOption::ServerIOThreadCount = 1;
720 int RuntimeOption::ServerHighQueueingThreshold = 60;
721 bool RuntimeOption::ServerLegacyBehavior = true;
722 int RuntimeOption::ServerHugeThreadCount = 0;
723 int RuntimeOption::ServerHugeStackKb = 384;
724 int RuntimeOption::ServerSchedPolicy = -1;
725 int RuntimeOption::ServerSchedPriority = 0;
726 uint32_t RuntimeOption::ServerLoopSampleRate = 0;
727 int RuntimeOption::ServerWarmupThrottleRequestCount = 0;
728 int RuntimeOption::ServerWarmupThrottleThreadCount = 0;
729 int RuntimeOption::ServerThreadDropCacheTimeoutSeconds = 0;
730 int RuntimeOption::ServerThreadJobLIFOSwitchThreshold = INT_MAX;
731 int RuntimeOption::ServerThreadJobMaxQueuingMilliSeconds = -1;
732 bool RuntimeOption::AlwaysDecodePostDataDefault = true;
733 bool RuntimeOption::ServerThreadDropStack = false;
734 bool RuntimeOption::ServerHttpSafeMode = false;
735 bool RuntimeOption::ServerStatCache = false;
736 bool RuntimeOption::ServerFixPathInfo = false;
737 bool RuntimeOption::ServerAddVaryEncoding = true;
738 bool RuntimeOption::ServerLogSettingsOnStartup = false;
739 bool RuntimeOption::ServerLogReorderProps = false;
740 bool RuntimeOption::ServerForkEnabled = true;
741 bool RuntimeOption::ServerForkLogging = false;
742 bool RuntimeOption::ServerWarmupConcurrently = false;
743 bool RuntimeOption::ServerDedupeWarmupRequests = false;
744 int RuntimeOption::ServerWarmupThreadCount = 1;
745 int RuntimeOption::ServerExtendedWarmupThreadCount = 1;
746 unsigned RuntimeOption::ServerExtendedWarmupRepeat = 1;
747 unsigned RuntimeOption::ServerExtendedWarmupDelaySeconds = 60;
748 std::vector<std::string> RuntimeOption::ServerWarmupRequests;
749 std::vector<std::string> RuntimeOption::ServerExtendedWarmupRequests;
750 std::string RuntimeOption::ServerCleanupRequest;
751 int RuntimeOption::ServerInternalWarmupThreads = 0;
752 boost::container::flat_set<std::string>
753 RuntimeOption::ServerHighPriorityEndPoints;
754 bool RuntimeOption::ServerExitOnBindFail;
755 int RuntimeOption::PageletServerThreadCount = 0;
756 int RuntimeOption::PageletServerHugeThreadCount = 0;
757 int RuntimeOption::PageletServerThreadDropCacheTimeoutSeconds = 0;
758 int RuntimeOption::PageletServerQueueLimit = 0;
759 bool RuntimeOption::PageletServerThreadDropStack = false;
760 int RuntimeOption::RequestTimeoutSeconds = 0;
761 int RuntimeOption::PspTimeoutSeconds = 0;
762 int RuntimeOption::PspCpuTimeoutSeconds = 0;
763 int64_t RuntimeOption::MaxRequestAgeFactor = 0;
764 int64_t RuntimeOption::RequestMemoryMaxBytes =
765 std::numeric_limits<int64_t>::max();
766 int64_t RuntimeOption::RequestHugeMaxBytes = 0;
767 int64_t RuntimeOption::ImageMemoryMaxBytes = 0;
768 int RuntimeOption::ServerGracefulShutdownWait = 0;
769 bool RuntimeOption::ServerHarshShutdown = true;
770 bool RuntimeOption::ServerEvilShutdown = true;
771 bool RuntimeOption::ServerKillOnTimeout = true;
772 bool RuntimeOption::Server503OnShutdownAbort = false;
773 int RuntimeOption::ServerPreShutdownWait = 0;
774 int RuntimeOption::ServerShutdownListenWait = 0;
775 int RuntimeOption::ServerShutdownEOMWait = 0;
776 int RuntimeOption::ServerPrepareToStopTimeout = 0;
777 int RuntimeOption::ServerPartialPostStatusCode = -1;
778 bool RuntimeOption::StopOldServer = false;
779 int RuntimeOption::OldServerWait = 30;
780 int RuntimeOption::CacheFreeFactor = 50;
781 int64_t RuntimeOption::ServerRSSNeededMb = 4096;
782 int64_t RuntimeOption::ServerCriticalFreeMb = 512;
783 std::vector<std::string> RuntimeOption::ServerNextProtocols;
784 bool RuntimeOption::ServerEnableH2C = false;
785 int RuntimeOption::BrotliCompressionEnabled = -1;
786 int RuntimeOption::BrotliChunkedCompressionEnabled = -1;
787 int RuntimeOption::BrotliCompressionMode = 0;
788 int RuntimeOption::BrotliCompressionQuality = 6;
789 int RuntimeOption::BrotliCompressionLgWindowSize = 20;
790 int RuntimeOption::ZstdCompressionEnabled = -1;
791 int RuntimeOption::ZstdCompressionLevel = 3;
792 int RuntimeOption::ZstdWindowLog = 0;
793 int RuntimeOption::ZstdChecksumRate = 0;
794 int RuntimeOption::GzipCompressionLevel = 3;
795 int RuntimeOption::GzipMaxCompressionLevel = 9;
796 bool RuntimeOption::EnableKeepAlive = true;
797 bool RuntimeOption::ExposeHPHP = true;
798 bool RuntimeOption::ExposeXFBServer = false;
799 bool RuntimeOption::ExposeXFBDebug = false;
800 std::string RuntimeOption::XFBDebugSSLKey;
801 int RuntimeOption::ConnectionTimeoutSeconds = -1;
802 bool RuntimeOption::EnableOutputBuffering = false;
803 std::string RuntimeOption::OutputHandler;
804 bool RuntimeOption::ImplicitFlush = false;
805 bool RuntimeOption::EnableEarlyFlush = true;
806 bool RuntimeOption::ForceChunkedEncoding = false;
807 int64_t RuntimeOption::MaxPostSize = 100;
808 int64_t RuntimeOption::LowestMaxPostSize = LLONG_MAX;
809 bool RuntimeOption::AlwaysPopulateRawPostData = false;
810 int64_t RuntimeOption::UploadMaxFileSize = 100;
811 std::string RuntimeOption::UploadTmpDir = "/tmp";
812 bool RuntimeOption::EnableFileUploads = true;
813 bool RuntimeOption::EnableUploadProgress = false;
814 int64_t RuntimeOption::MaxFileUploads = 20;
815 int RuntimeOption::Rfc1867Freq = 256 * 1024;
816 std::string RuntimeOption::Rfc1867Prefix = "vupload_";
817 std::string RuntimeOption::Rfc1867Name = "video_ptoken";
818 bool RuntimeOption::ExpiresActive = true;
819 int RuntimeOption::ExpiresDefault = 2592000;
820 std::string RuntimeOption::DefaultCharsetName = "";
821 bool RuntimeOption::ForceServerNameToHeader = false;
822 bool RuntimeOption::PathDebug = false;
824 int64_t RuntimeOption::RequestBodyReadLimit = -1;
826 bool RuntimeOption::EnableSSL = false;
827 int RuntimeOption::SSLPort = 443;
828 int RuntimeOption::SSLPortFd = -1;
829 std::string RuntimeOption::SSLCertificateFile;
830 std::string RuntimeOption::SSLCertificateKeyFile;
831 std::string RuntimeOption::SSLCertificateDir;
832 std::string RuntimeOption::SSLTicketSeedFile;
833 bool RuntimeOption::TLSDisableTLS1_2 = false;
834 std::string RuntimeOption::TLSClientCipherSpec;
835 bool RuntimeOption::EnableSSLWithPlainText = false;
836 int RuntimeOption::SSLClientAuthLevel = 0;
837 std::string RuntimeOption::SSLClientCAFile = "";
839 std::string RuntimeOption::ClientAuthAclIdentity;
840 std::string RuntimeOption::ClientAuthAclAction;
841 bool RuntimeOption::ClientAuthFailClose = false;
842 uint32_t RuntimeOption::SSLClientAuthLoggingSampleRatio = 0;
843 uint32_t RuntimeOption::ClientAuthSuccessLogSampleRatio = 0;
844 uint32_t RuntimeOption::ClientAuthFailureLogSampleRatio = 0;
845 uint32_t RuntimeOption::ClientAuthLogSampleBase = 100;
847 std::vector<std::shared_ptr<VirtualHost>> RuntimeOption::VirtualHosts;
848 std::shared_ptr<IpBlockMap> RuntimeOption::IpBlocks;
849 std::vector<std::shared_ptr<SatelliteServerInfo>>
850 RuntimeOption::SatelliteServerInfos;
852 bool RuntimeOption::AllowRunAsRoot = false; // Allow running hhvm as root.
854 int RuntimeOption::XboxServerThreadCount = 10;
855 int RuntimeOption::XboxServerMaxQueueLength = INT_MAX;
856 int RuntimeOption::XboxServerInfoMaxRequest = 500;
857 int RuntimeOption::XboxServerInfoDuration = 120;
858 std::string RuntimeOption::XboxServerInfoReqInitFunc;
859 std::string RuntimeOption::XboxServerInfoReqInitDoc;
860 bool RuntimeOption::XboxServerInfoAlwaysReset = false;
861 bool RuntimeOption::XboxServerLogInfo = false;
862 std::string RuntimeOption::XboxProcessMessageFunc = "xbox_process_message";
863 std::string RuntimeOption::XboxPassword;
864 std::set<std::string> RuntimeOption::XboxPasswords;
866 std::string RuntimeOption::SourceRoot = Process::GetCurrentDirectory() + '/';
867 std::vector<std::string> RuntimeOption::IncludeSearchPaths;
868 std::map<std::string, std::string> RuntimeOption::IncludeRoots;
869 std::map<std::string, std::string> RuntimeOption::AutoloadRoots;
870 bool RuntimeOption::AutoloadEnabled;
871 std::string RuntimeOption::AutoloadDBPath;
872 std::string RuntimeOption::AutoloadDBPerms{"0644"};
873 std::string RuntimeOption::AutoloadDBGroup;
874 std::string RuntimeOption::AutoloadLogging;
875 std::vector<std::string> RuntimeOption::AutoloadExcludedRepos;
876 bool RuntimeOption::AutoloadLoggingAllowPropagation;
877 bool RuntimeOption::AutoloadEnforceOneDefinitionRule = true;
878 bool RuntimeOption::AutoloadRethrowExceptions = true;
879 std::string RuntimeOption::FileCache;
880 std::string RuntimeOption::DefaultDocument;
881 std::string RuntimeOption::GlobalDocument;
882 std::string RuntimeOption::ErrorDocument404;
883 bool RuntimeOption::ForbiddenAs404 = false;
884 std::string RuntimeOption::ErrorDocument500;
885 std::string RuntimeOption::FatalErrorMessage;
886 std::string RuntimeOption::FontPath;
887 bool RuntimeOption::EnableStaticContentFromDisk = true;
888 bool RuntimeOption::EnableOnDemandUncompress = true;
889 bool RuntimeOption::EnableStaticContentMMap = true;
891 bool RuntimeOption::Utf8izeReplace = true;
893 std::string RuntimeOption::RequestInitFunction;
894 std::string RuntimeOption::RequestInitDocument;
895 std::string RuntimeOption::AutoPrependFile;
896 std::string RuntimeOption::AutoAppendFile;
898 bool RuntimeOption::SafeFileAccess = false;
899 std::vector<std::string> RuntimeOption::AllowedDirectories;
900 std::set<std::string> RuntimeOption::AllowedFiles;
901 hphp_string_imap<std::string> RuntimeOption::StaticFileExtensions;
902 hphp_string_imap<std::string> RuntimeOption::PhpFileExtensions;
903 std::set<std::string> RuntimeOption::ForbiddenFileExtensions;
904 std::vector<std::shared_ptr<FilesMatch>> RuntimeOption::FilesMatches;
906 bool RuntimeOption::WhitelistExec = false;
907 bool RuntimeOption::WhitelistExecWarningOnly = false;
908 std::vector<std::string> RuntimeOption::AllowedExecCmds;
910 bool RuntimeOption::UnserializationWhitelistCheck = false;
911 bool RuntimeOption::UnserializationWhitelistCheckWarningOnly = true;
912 int64_t RuntimeOption::UnserializationBigMapThreshold = 1 << 16;
914 std::string RuntimeOption::TakeoverFilename;
915 std::string RuntimeOption::AdminServerIP;
916 int RuntimeOption::AdminServerPort = 0;
917 int RuntimeOption::AdminThreadCount = 1;
918 bool RuntimeOption::AdminServerEnableSSLWithPlainText = false;
919 bool RuntimeOption::AdminServerStatsNeedPassword = true;
920 std::string RuntimeOption::AdminPassword;
921 std::set<std::string> RuntimeOption::AdminPasswords;
922 std::set<std::string> RuntimeOption::HashedAdminPasswords;
923 std::string RuntimeOption::AdminDumpPath;
925 std::string RuntimeOption::ProxyOriginRaw;
926 int RuntimeOption::ProxyPercentageRaw = 0;
927 int RuntimeOption::ProxyRetry = 3;
928 bool RuntimeOption::UseServeURLs;
929 std::set<std::string> RuntimeOption::ServeURLs;
930 bool RuntimeOption::UseProxyURLs;
931 std::set<std::string> RuntimeOption::ProxyURLs;
932 std::vector<std::string> RuntimeOption::ProxyPatterns;
933 bool RuntimeOption::AlwaysUseRelativePath = false;
935 int RuntimeOption::HttpDefaultTimeout = 30;
936 int RuntimeOption::HttpSlowQueryThreshold = 5000; // ms
938 bool RuntimeOption::NativeStackTrace = false;
939 bool RuntimeOption::ServerErrorMessage = false;
940 bool RuntimeOption::RecordInput = false;
941 bool RuntimeOption::ClearInputOnSuccess = true;
942 std::string RuntimeOption::ProfilerOutputDir = "/tmp";
943 std::string RuntimeOption::CoreDumpEmail;
944 bool RuntimeOption::CoreDumpReport = true;
945 std::string RuntimeOption::CoreDumpReportDirectory =
946 #if defined(HPHP_OSS)
947 "/tmp";
948 #else
949 "/var/tmp/cores";
950 #endif
951 std::string RuntimeOption::StackTraceFilename;
952 int RuntimeOption::StackTraceTimeout = 0; // seconds; 0 means unlimited
953 std::string RuntimeOption::RemoteTraceOutputDir = "/tmp";
954 std::set<std::string, stdltistr> RuntimeOption::TraceFunctions;
956 bool RuntimeOption::EnableStats = false;
957 bool RuntimeOption::EnableAPCStats = false;
958 bool RuntimeOption::EnableWebStats = false;
959 bool RuntimeOption::EnableMemoryStats = false;
960 bool RuntimeOption::EnableSQLStats = false;
961 bool RuntimeOption::EnableSQLTableStats = false;
962 bool RuntimeOption::EnableNetworkIOStatus = false;
963 std::string RuntimeOption::StatsXSL;
964 std::string RuntimeOption::StatsXSLProxy;
965 uint32_t RuntimeOption::StatsSlotDuration = 10 * 60; // 10 minutes
966 uint32_t RuntimeOption::StatsMaxSlot = 12 * 6; // 12 hours
968 int64_t RuntimeOption::MaxSQLRowCount = 0;
969 int64_t RuntimeOption::SocketDefaultTimeout = 60;
970 bool RuntimeOption::LockCodeMemory = false;
971 int RuntimeOption::MaxArrayChain = INT_MAX;
972 bool RuntimeOption::WarnOnCollectionToArray = false;
973 bool RuntimeOption::UseDirectCopy = false;
975 #if FOLLY_SANITIZE
976 bool RuntimeOption::DisableSmallAllocator = true;
977 #else
978 bool RuntimeOption::DisableSmallAllocator = false;
979 #endif
981 std::map<std::string, std::string> RuntimeOption::ServerVariables;
982 std::map<std::string, std::string> RuntimeOption::EnvVariables;
984 std::string RuntimeOption::LightProcessFilePrefix = "./lightprocess";
985 int RuntimeOption::LightProcessCount = 0;
987 int64_t RuntimeOption::HeapSizeMB = 4096; // 4gb
988 int64_t RuntimeOption::HeapResetCountBase = 1;
989 int64_t RuntimeOption::HeapResetCountMultiple = 2;
990 int64_t RuntimeOption::HeapLowWaterMark = 16;
991 int64_t RuntimeOption::HeapHighWaterMark = 1024;
992 uint64_t RuntimeOption::DisableCallUserFunc = 0;
993 uint64_t RuntimeOption::DisableCallUserFuncArray = 0;
994 uint64_t RuntimeOption::DisableConstant = 0;
995 bool RuntimeOption::DisableNontoplevelDeclarations = false;
996 bool RuntimeOption::EnableClassLevelWhereClauses = false;
999 std::string RuntimeOption::WatchmanRootSocket;
1000 std::string RuntimeOption::WatchmanDefaultSocket;
1002 #ifdef HHVM_DYNAMIC_EXTENSION_DIR
1003 std::string RuntimeOption::ExtensionDir = HHVM_DYNAMIC_EXTENSION_DIR;
1004 #else
1005 std::string RuntimeOption::ExtensionDir = "";
1006 #endif
1008 std::vector<std::string> RuntimeOption::Extensions;
1009 std::vector<std::string> RuntimeOption::DynamicExtensions;
1010 std::string RuntimeOption::DynamicExtensionPath = ".";
1011 int RuntimeOption::CheckCLIClientCommands = 0;
1013 int RuntimeOption::CheckIntOverflow = 0;
1014 HackStrictOption
1015 RuntimeOption::StrictArrayFillKeys = HackStrictOption::OFF;
1017 // defaults set when the INI option is bound - values below are irrelevant.
1018 bool RuntimeOption::LookForTypechecker = false;
1019 bool RuntimeOption::AutoTypecheck = false;
1021 bool RuntimeOption::PHP7_EngineExceptions = false;
1022 bool RuntimeOption::PHP7_NoHexNumerics = false;
1023 bool RuntimeOption::PHP7_Builtins = false;
1024 bool RuntimeOption::PHP7_Substr = false;
1025 bool RuntimeOption::PHP7_DisallowUnsafeCurlUploads = false;
1027 int RuntimeOption::GetScannerType() {
1028 int type = 0;
1029 if (EnableShortTags) type |= Scanner::AllowShortTags;
1030 return type;
1033 const std::string& RuntimeOption::GetServerPrimaryIPv4() {
1034 static std::string serverPrimaryIPv4 = GetPrimaryIPv4();
1035 return serverPrimaryIPv4;
1038 const std::string& RuntimeOption::GetServerPrimaryIPv6() {
1039 static std::string serverPrimaryIPv6 = GetPrimaryIPv6();
1040 return serverPrimaryIPv6;
1043 static inline std::string regionSelectorDefault() {
1044 return "tracelet";
1047 static inline bool pgoDefault() {
1048 #ifdef HHVM_NO_DEFAULT_PGO
1049 return false;
1050 #else
1051 return true;
1052 #endif
1055 static inline bool eagerGcDefault() {
1056 #ifdef HHVM_EAGER_GC
1057 return true;
1058 #else
1059 return false;
1060 #endif
1063 static inline bool enableGcDefault() {
1064 return RuntimeOption::EvalEagerGC;
1067 static inline uint64_t pgoThresholdDefault() {
1068 return debug ? 2 : 2000;
1071 static inline bool alignMacroFusionPairs() {
1072 switch (getProcessorFamily()) {
1073 case ProcessorFamily::Intel_SandyBridge:
1074 case ProcessorFamily::Intel_IvyBridge:
1075 case ProcessorFamily::Intel_Haswell:
1076 case ProcessorFamily::Intel_Broadwell:
1077 case ProcessorFamily::Intel_Skylake:
1078 case ProcessorFamily::Intel_Cooperlake:
1079 return true;
1080 case ProcessorFamily::Unknown:
1081 return false;
1083 return false;
1086 static inline bool armLseDefault() {
1087 #if defined (__linux__) && defined (__aarch64__) && defined (HWCAP_ATOMICS)
1088 return (getauxval(AT_HWCAP) & HWCAP_ATOMICS) != 0;
1089 #else
1090 return false;
1091 #endif
1094 static inline bool evalJitDefault() {
1095 #ifdef _MSC_VER
1096 return false;
1097 #else
1098 return true;
1099 #endif
1102 static inline bool reuseTCDefault() {
1103 return hhvm_reuse_tc && !RuntimeOption::RepoAuthoritative;
1106 static inline bool useFileBackedArenaDefault() {
1107 return RuntimeOption::RepoAuthoritative &&
1108 RuntimeOption::ServerExecutionMode();
1111 static inline bool hugePagesSoundNice() {
1112 return RuntimeOption::ServerExecutionMode();
1115 static inline uint32_t hotTextHugePagesDefault() {
1116 if (!hugePagesSoundNice()) return 0;
1117 return arch() == Arch::ARM ? 12 : 8;
1120 static inline std::string reorderPropsDefault() {
1121 if (isJitDeserializing()) {
1122 return "countedness-hotness";
1124 return debug ? "alphabetical" : "countedness";
1127 static inline uint32_t profileRequestsDefault() {
1128 return debug ? std::numeric_limits<uint32_t>::max() : 2500;
1131 static inline uint32_t profileBCSizeDefault() {
1132 return debug ? std::numeric_limits<uint32_t>::max()
1133 : RuntimeOption::EvalJitConcurrently ? 3750000
1134 : 4300000;
1137 static inline uint32_t resetProfCountersDefault() {
1138 return RuntimeOption::EvalJitPGORacyProfiling
1139 ? std::numeric_limits<uint32_t>::max()
1140 : RuntimeOption::EvalJitConcurrently ? 250 : 1000;
1143 static inline int retranslateAllRequestDefault() {
1144 return RuntimeOption::ServerExecutionMode() ? 1000000 : 0;
1147 static inline int retranslateAllSecondsDefault() {
1148 return RuntimeOption::ServerExecutionMode() ? 180 : 0;
1151 static inline bool pgoLayoutSplitHotColdDefault() {
1152 return arch() != Arch::ARM;
1155 static inline bool layoutPrologueSplitHotColdDefault() {
1156 return arch() != Arch::ARM;
1159 Optional<folly::fs::path> RuntimeOption::GetHomePath(
1160 const folly::StringPiece user) {
1162 auto homePath = folly::fs::path{RuntimeOption::SandboxHome}
1163 / folly::fs::path{user};
1164 if (folly::fs::is_directory(homePath)) {
1165 return {std::move(homePath)};
1168 if (!RuntimeOption::SandboxFallback.empty()) {
1169 homePath = folly::fs::path{RuntimeOption::SandboxFallback}
1170 / folly::fs::path{user};
1171 if (folly::fs::is_directory(homePath)) {
1172 return {std::move(homePath)};
1176 return {};
1179 std::string RuntimeOption::GetDefaultUser() {
1180 if (SandboxDefaultUserFile.empty()) return {};
1182 folly::fs::path file{SandboxDefaultUserFile};
1183 if (!folly::fs::is_regular_file(file)) return {};
1185 std::string user;
1186 if (!folly::readFile(file.c_str(), user) || user.empty()) return {};
1188 return user;
1191 bool RuntimeOption::ReadPerUserSettings(const folly::fs::path& confFileName,
1192 IniSettingMap& ini, Hdf& config) {
1193 try {
1194 Config::ParseConfigFile(confFileName.native(), ini, config, false);
1195 return true;
1196 } catch (HdfException& e) {
1197 Logger::Error("%s ignored: %s", confFileName.native().c_str(),
1198 e.getMessage().c_str());
1199 return false;
1203 std::string RuntimeOption::getUnitCacheBreakingOptions() {
1204 return folly::to<std::string>(
1205 RuntimeOption::EnableClassLevelWhereClauses,
1206 RuntimeOption::EvalGenerateDocComments,
1207 RuntimeOption::EnableXHP,
1208 RuntimeOption::EvalEnableCallBuiltin,
1209 RuntimeOption::EvalHackArrCompatSerializeNotices,
1210 RuntimeOption::EvalHackCompilerVerboseErrors,
1211 RuntimeOption::EvalJitEnableRenameFunction,
1212 RuntimeOption::EvalLoadFilepathFromUnitCache,
1213 RuntimeOption::EvalForbidDynamicCallsToFunc,
1214 RuntimeOption::EvalForbidDynamicCallsToClsMeth,
1215 RuntimeOption::EvalForbidDynamicCallsToInstMeth,
1216 RuntimeOption::EvalForbidDynamicConstructs,
1217 RuntimeOption::EvalForbidDynamicCallsWithAttr,
1218 RuntimeOption::EvalLogKnownMethodsAsDynamicCalls,
1219 RuntimeOption::EvalNoticeOnBuiltinDynamicCalls,
1220 RuntimeOption::EvalEnableReadonlyPropertyEnforcement,
1221 RuntimeOption::EvalAssemblerFoldDefaultValues,
1222 RuntimeOption::RepoDebugInfo,
1223 RuntimeOption::CheckIntOverflow,
1224 RuntimeOption::DisableNontoplevelDeclarations,
1225 RuntimeOption::EvalEnableImplicitContext,
1226 RuntimeOption::EvalEmitClsMethPointers,
1227 RuntimeOption::EvalIsVecNotices,
1228 RuntimeOption::EvalAllowHhas,
1229 RuntimeOption::EvalEnforceGenericsUB,
1230 RuntimeOption::EvalEmitMethCallerFuncPointers,
1231 RuntimeOption::EvalAssemblerMaxScalarSize,
1232 RuntimeOption::EvalEmitClassPointers,
1233 RuntimeOption::EvalFoldLazyClassKeys,
1234 RuntimeOption::EvalEnableAbstractContextConstants,
1235 RuntimeOption::EvalTraitConstantInterfaceBehavior,
1236 '|', RuntimeOption::EvalUnitCacheBreaker, '|',
1237 RuntimeOption::EvalDiamondTraitMethods,
1238 RuntimeOption::PHP7_NoHexNumerics,
1239 RuntimeOption::PHP7_Builtins,
1240 RuntimeOption::PHP7_Substr,
1241 '|', CoeffectsConfig::mangle(), '|');
1244 std::string RuntimeOption::getTraceOutputFile() {
1245 return folly::sformat("{}/hphp.{}.log",
1246 RuntimeOption::RemoteTraceOutputDir, (int64_t)getpid());
1249 const uint64_t kEvalVMStackElmsDefault =
1250 #if defined(VALGRIND) && !FOLLY_SANITIZE
1251 0x800
1252 #else
1253 0x4000
1254 #endif
1257 constexpr uint32_t kEvalVMInitialGlobalTableSizeDefault = 512;
1258 constexpr uint64_t kJitRelocationSizeDefault = 1 << 20;
1260 static const bool kJitTimerDefault =
1261 #ifdef ENABLE_JIT_TIMER_DEFAULT
1262 true
1263 #else
1264 false
1265 #endif
1268 using std::string;
1269 #define F(type, name, def) \
1270 type RuntimeOption::Eval ## name = type(def);
1271 EVALFLAGS();
1272 #undef F
1273 hphp_string_imap<TypedValue> RuntimeOption::ConstantFunctions;
1275 bool RuntimeOption::RecordCodeCoverage = false;
1276 std::string RuntimeOption::CodeCoverageOutputFile;
1278 std::string RuntimeOption::RepoPath;
1279 RepoMode RuntimeOption::RepoLocalMode = RepoMode::ReadOnly;
1280 std::string RuntimeOption::RepoLocalPath;
1281 RepoMode RuntimeOption::RepoCentralMode = RepoMode::ReadWrite;
1282 std::string RuntimeOption::RepoCentralPath;
1283 int32_t RuntimeOption::RepoCentralFileMode;
1284 std::string RuntimeOption::RepoCentralFileUser;
1285 std::string RuntimeOption::RepoCentralFileGroup;
1286 std::string RuntimeOption::RepoJournal = "delete";
1287 bool RuntimeOption::RepoAllowFallbackPath = true;
1288 bool RuntimeOption::RepoCommit = true;
1289 bool RuntimeOption::RepoDebugInfo = true;
1290 bool RuntimeOption::RepoLitstrLazyLoad = true;
1291 // Missing: RuntimeOption::RepoAuthoritative's physical location is
1292 // perf-sensitive.
1293 bool RuntimeOption::RepoLocalReadaheadConcurrent = false;
1294 int64_t RuntimeOption::RepoLocalReadaheadRate = 0;
1295 uint32_t RuntimeOption::RepoBusyTimeoutMS = 15000;
1297 bool RuntimeOption::HHProfEnabled = false;
1298 bool RuntimeOption::HHProfActive = false;
1299 bool RuntimeOption::HHProfAccum = false;
1300 bool RuntimeOption::HHProfRequest = false;
1302 bool RuntimeOption::SandboxMode = false;
1303 std::string RuntimeOption::SandboxPattern;
1304 std::string RuntimeOption::SandboxHome;
1305 std::string RuntimeOption::SandboxFallback;
1306 std::string RuntimeOption::SandboxConfFile;
1307 std::map<std::string, std::string> RuntimeOption::SandboxServerVariables;
1308 bool RuntimeOption::SandboxFromCommonRoot = false;
1309 std::string RuntimeOption::SandboxDirectoriesRoot;
1310 std::string RuntimeOption::SandboxLogsRoot;
1311 std::string RuntimeOption::SandboxDefaultUserFile;
1312 std::string RuntimeOption::SandboxHostAlias;
1314 bool RuntimeOption::EnableHphpdDebugger = false;
1315 bool RuntimeOption::EnableVSDebugger = false;
1316 int RuntimeOption::VSDebuggerListenPort = -1;
1317 std::string RuntimeOption::VSDebuggerDomainSocketPath;
1318 bool RuntimeOption::VSDebuggerNoWait = false;
1319 bool RuntimeOption::EnableDebuggerColor = true;
1320 bool RuntimeOption::EnableDebuggerPrompt = true;
1321 bool RuntimeOption::EnableDebuggerServer = false;
1322 bool RuntimeOption::EnableDebuggerUsageLog = false;
1323 bool RuntimeOption::DebuggerDisableIPv6 = false;
1324 std::string RuntimeOption::DebuggerServerIP;
1325 int RuntimeOption::DebuggerServerPort = 8089;
1326 std::string RuntimeOption::DebuggerDefaultSandboxPath;
1327 std::string RuntimeOption::DebuggerStartupDocument;
1328 int RuntimeOption::DebuggerSignalTimeout = 1;
1329 std::string RuntimeOption::DebuggerAuthTokenScriptBin;
1330 std::string RuntimeOption::DebuggerSessionAuthScriptBin;
1332 std::string RuntimeOption::SendmailPath = "sendmail -t -i";
1333 std::string RuntimeOption::MailForceExtraParameters;
1335 int64_t RuntimeOption::PregBacktraceLimit = 1000000;
1336 int64_t RuntimeOption::PregRecursionLimit = 100000;
1337 bool RuntimeOption::EnablePregErrorLog = true;
1339 bool RuntimeOption::SimpleXMLEmptyNamespaceMatchesAll = false;
1341 bool RuntimeOption::EnableHotProfiler = true;
1342 int RuntimeOption::ProfilerTraceBuffer = 2000000;
1343 double RuntimeOption::ProfilerTraceExpansion = 1.2;
1344 int RuntimeOption::ProfilerMaxTraceBuffer = 0;
1346 #ifdef FACEBOOK
1347 bool RuntimeOption::EnableFb303Server = false;
1348 int RuntimeOption::Fb303ServerPort = 0;
1349 std::string RuntimeOption::Fb303ServerIP;
1350 int RuntimeOption::Fb303ServerThreadStackSizeMb = 8;
1351 int RuntimeOption::Fb303ServerWorkerThreads = 1;
1352 int RuntimeOption::Fb303ServerPoolThreads = 1;
1353 #endif
1355 double RuntimeOption::XenonPeriodSeconds = 0.0;
1356 uint32_t RuntimeOption::XenonRequestFreq = 1;
1357 bool RuntimeOption::XenonForceAlwaysOn = false;
1359 bool RuntimeOption::StrobelightEnabled = false;
1361 bool RuntimeOption::TrackPerUnitMemory = false;
1363 bool RuntimeOption::SetProfileNullThisObject = true;
1365 bool RuntimeOption::ApplySecondaryQueuePenalty = false;
1367 std::map<std::string, std::string> RuntimeOption::CustomSettings;
1369 #ifdef NDEBUG
1370 #ifdef ALWAYS_ASSERT
1371 const StaticString s_hhvm_build_type("Release with asserts");
1372 #else
1373 const StaticString s_hhvm_build_type("Release");
1374 #endif
1375 #else
1376 const StaticString s_hhvm_build_type("Debug");
1377 #endif
1379 ///////////////////////////////////////////////////////////////////////////////
1381 static void setResourceLimit(int resource, const IniSetting::Map& ini,
1382 const Hdf& rlimit, const char* nodeName) {
1383 if (!Config::GetString(ini, rlimit, nodeName).empty()) {
1384 struct rlimit rl;
1385 getrlimit(resource, &rl);
1386 rl.rlim_cur = Config::GetInt64(ini, rlimit, nodeName);
1387 if (rl.rlim_max < rl.rlim_cur) {
1388 rl.rlim_max = rl.rlim_cur;
1390 int ret = setrlimit(resource, &rl);
1391 if (ret) {
1392 Logger::Error("Unable to set %s to %" PRId64 ": %s (%d)",
1393 nodeName, (int64_t)rl.rlim_cur,
1394 folly::errnoStr(errno).c_str(), errno);
1399 static void normalizePath(std::string &path) {
1400 if (!path.empty()) {
1401 if (path[path.length() - 1] == '/') {
1402 path = path.substr(0, path.length() - 1);
1404 if (path[0] != '/') {
1405 path = std::string("/") + path;
1410 static String todayDate() {
1411 time_t rawtime;
1412 struct tm timeinfo;
1413 char buf[256];
1414 time(&rawtime);
1415 localtime_r(&rawtime, &timeinfo);
1416 strftime(buf, sizeof(buf), "%Y-%m-%d", &timeinfo);
1417 return buf;
1420 static bool matchShard(
1421 bool enableShards,
1422 const std::string& hostname,
1423 const IniSetting::Map& ini, Hdf hdfPattern,
1424 std::vector<std::string>& messages
1426 if (!hdfPattern.exists("Shard")) return true;
1428 if (!enableShards) {
1429 hdfPattern["Shard"].setVisited();
1430 hdfPattern["ShardCount"].setVisited();
1431 hdfPattern["ShardSalt"].setVisited();
1432 return false;
1435 auto const shard = Config::GetInt64(ini, hdfPattern, "Shard", -1, false);
1437 auto const nshards =
1438 Config::GetInt64(ini, hdfPattern, "ShardCount", 100, false);
1440 if (shard < 0 || shard >= nshards) {
1441 messages.push_back(folly::sformat("Invalid value for Shard: {}", shard));
1442 return true;
1445 auto input = hostname;
1446 if (hdfPattern.exists("ShardSalt")) {
1447 auto salt = Config::GetString(ini, hdfPattern, "ShardSalt", "", false);
1448 salt = string_replace(salt, "%{date}", todayDate()).toCppString();
1449 input += salt;
1452 auto const md5 = Md5Digest(input.data(), input.size());
1453 uint32_t seed{0};
1454 memcpy(&seed, &md5.digest[0], 4);
1456 // This shift is to match the behavior of sharding in chef which appears to
1457 // have an off-by-one bug:
1458 // seed = Digest::MD5.hexdigest(seed_input)[0...7].to_i(16)
1459 seed = ntohl(seed) >> 4;
1461 messages.push_back(folly::sformat(
1462 "Checking Shard = {}; Input = {}; Seed = {}; ShardCount = {}; Value = {}",
1463 shard, input, seed, nshards, seed % nshards
1466 return seed % nshards <= shard;
1469 // A machine can belong to a tier, which can overwrite
1470 // various settings, even if they are set in the same
1471 // hdf file. However, CLI overrides still win the day over
1472 // everything.
1473 static std::vector<std::string> getTierOverwrites(IniSetting::Map& ini,
1474 Hdf& config) {
1476 // Machine metrics
1477 string hostname, tier, task, cpu, tiers, tags;
1479 hostname = Config::GetString(ini, config, "Machine.name");
1480 if (hostname.empty()) {
1481 hostname = Process::GetHostName();
1484 tier = Config::GetString(ini, config, "Machine.tier");
1486 task = Config::GetString(ini, config, "Machine.task");
1488 cpu = Config::GetString(ini, config, "Machine.cpu");
1489 if (cpu.empty()) {
1490 cpu = Process::GetCPUModel();
1493 tiers = Config::GetString(ini, config, "Machine.tiers");
1494 if (!tiers.empty()) {
1495 if (!folly::readFile(tiers.c_str(), tiers)) {
1496 tiers.clear();
1500 tags = Config::GetString(ini, config, "Machine.tags");
1501 if (!tags.empty()) {
1502 if (!folly::readFile(tags.c_str(), tags)) {
1503 tags.clear();
1508 auto const checkPatterns = [&] (Hdf hdf) {
1509 // Check the patterns using "&" rather than "&&" so they all get
1510 // evaluated; otherwise with multiple patterns, if an earlier
1511 // one fails to match, the later one is reported as unused.
1512 return
1513 Config::matchHdfPattern(hostname, ini, hdf, "machine") &
1514 Config::matchHdfPattern(tier, ini, hdf, "tier") &
1515 Config::matchHdfPattern(task, ini, hdf, "task") &
1516 Config::matchHdfPattern(tiers, ini, hdf, "tiers", "m") &
1517 Config::matchHdfPattern(tags, ini, hdf, "tags", "m") &
1518 Config::matchHdfPattern(cpu, ini, hdf, "cpu");
1521 std::vector<std::string> messages;
1522 auto enableShards = true;
1524 // Tier overwrites
1526 for (Hdf hdf = config["Tiers"].firstChild(); hdf.exists();
1527 hdf = hdf.next()) {
1528 if (messages.empty()) {
1529 messages.emplace_back(folly::sformat(
1530 "Matching tiers using: "
1531 "machine='{}', tier='{}', task='{}', "
1532 "cpu='{}', tiers='{}', tags='{}'",
1533 hostname, tier, task, cpu, tiers, tags));
1535 // Check the patterns using "&" rather than "&&" so they all get
1536 // evaluated; otherwise with multiple patterns, if an earlier
1537 // one fails to match, the later one is reported as unused.
1538 if (checkPatterns(hdf) &
1539 (!hdf.exists("exclude") || !checkPatterns(hdf["exclude"])) &
1540 matchShard(enableShards, hostname, ini, hdf, messages)) {
1541 messages.emplace_back(folly::sformat(
1542 "Matched tier: {}", hdf.getName()));
1543 if (enableShards && hdf["DisableShards"].configGetBool()) {
1544 messages.emplace_back("Sharding is disabled.");
1545 enableShards = false;
1547 if (hdf.exists("clear")) {
1548 std::vector<std::string> list;
1549 hdf["clear"].configGet(list);
1550 for (auto const& s : list) {
1551 config.remove(s);
1554 config.copy(hdf["overwrite"]);
1555 // no break here, so we can continue to match more overwrites
1557 // Avoid lint errors about unvisited nodes when the tier does not match.
1558 hdf["DisableShards"].setVisited();
1559 hdf["clear"].setVisited();
1560 hdf["overwrite"].setVisited();
1563 return messages;
1566 void RuntimeOption::ReadSatelliteInfo(
1567 const IniSettingMap& ini,
1568 const Hdf& hdf,
1569 std::vector<std::shared_ptr<SatelliteServerInfo>>& infos,
1570 std::string& xboxPassword,
1571 std::set<std::string>& xboxPasswords) {
1572 auto ss_callback = [&] (const IniSettingMap &ini_ss, const Hdf &hdf_ss,
1573 const std::string &ini_ss_key) {
1574 auto satellite = std::make_shared<SatelliteServerInfo>(ini_ss, hdf_ss,
1575 ini_ss_key);
1576 infos.push_back(satellite);
1577 if (satellite->getType() == SatelliteServer::Type::KindOfRPCServer) {
1578 xboxPassword = satellite->getPassword();
1579 xboxPasswords = satellite->getPasswords();
1582 Config::Iterate(ss_callback, ini, hdf, "Satellites");
1585 extern void initialize_apc();
1586 void RuntimeOption::Load(
1587 IniSetting::Map& ini, Hdf& config,
1588 const std::vector<std::string>& iniClis /* = std::vector<std::string>() */,
1589 const std::vector<std::string>& hdfClis /* = std::vector<std::string>() */,
1590 std::vector<std::string>* messages /* = nullptr */,
1591 std::string cmd /* = "" */) {
1593 // Intialize the memory manager here because various settings and
1594 // initializations that we do here need it
1595 tl_heap.getCheck();
1597 // Get the ini (-d) and hdf (-v) strings, which may override some
1598 // of options that were set from config files. We also do these
1599 // now so we can override Tier.*.[machine | tier | cpu] on the
1600 // command line, along with any fields within a Tier (e.g.,
1601 // CoreFileSize)
1602 for (auto& istr : iniClis) {
1603 Config::ParseIniString(istr, ini);
1605 for (auto& hstr : hdfClis) {
1606 Config::ParseHdfString(hstr, config);
1609 // See if there are any Tier-based overrides
1610 auto m = getTierOverwrites(ini, config);
1611 if (messages) *messages = std::move(m);
1613 // RelativeConfigs can be set by commandline flags and tier overwrites, they
1614 // may also contain tier overwrites. They are, however, only included once, so
1615 // relative configs may not specify other relative configs which must to be
1616 // loaded. If RelativeConfigs is modified while loading configs an error is
1617 // raised, but we defer doing so until the logger is initialized below. If a
1618 // relative config cannot be found it is silently skipped (this is to allow
1619 // configs to be conditionally applied to scripts based on their location). By
1620 // reading the "hhvm.relative_configs" ini setting at runtime it is possible
1621 // to determine which configs were actually loaded.
1622 std::string relConfigsError;
1623 Config::Bind(s_RelativeConfigs, ini, config, "RelativeConfigs");
1624 if (!cmd.empty() && !s_RelativeConfigs.empty()) {
1625 String strcmd(cmd, CopyString);
1626 Process::InitProcessStatics();
1627 auto const currentDir = Process::CurrentWorkingDirectory.data();
1628 std::vector<std::string> newConfigs;
1629 auto const original = s_RelativeConfigs;
1630 for (auto& str : original) {
1631 if (str.empty()) continue;
1633 std::string fullpath;
1634 auto const found = FileUtil::runRelative(
1635 str, strcmd, currentDir,
1636 [&] (const String& f) {
1637 if (access(f.data(), R_OK) == 0) {
1638 fullpath = f.toCppString();
1639 FTRACE_MOD(Trace::facts, 3, "Parsing {}\n", fullpath);
1640 Config::ParseConfigFile(fullpath, ini, config);
1641 return true;
1643 return false;
1646 if (found) newConfigs.emplace_back(std::move(fullpath));
1648 if (!newConfigs.empty()) {
1649 auto m2 = getTierOverwrites(ini, config);
1650 if (messages) *messages = std::move(m2);
1651 if (s_RelativeConfigs != original) {
1652 relConfigsError = folly::sformat(
1653 "RelativeConfigs node was modified while loading configs from [{}] "
1654 "to [{}]",
1655 folly::join(", ", original),
1656 folly::join(", ", s_RelativeConfigs)
1660 s_RelativeConfigs.swap(newConfigs);
1661 } else {
1662 s_RelativeConfigs.clear();
1665 // Then get the ini and hdf cli strings again, in case the tier overwrites
1666 // overrode any non-tier based command line option we set. The tier-based
1667 // command line overwrites will already have been set in the call above.
1668 // This extra call is for the other command line options that may have been
1669 // overridden by a tier, but shouldn't have been.
1670 for (auto& istr : iniClis) {
1671 Config::ParseIniString(istr, ini);
1673 for (auto& hstr : hdfClis) {
1674 Config::ParseHdfString(hstr, config);
1677 Config::Bind(PidFile, ini, config, "PidFile", "www.pid");
1678 Config::Bind(DeploymentId, ini, config, "DeploymentId");
1681 static std::string deploymentIdOverride;
1682 Config::Bind(deploymentIdOverride, ini, config, "DeploymentIdOverride");
1683 if (!deploymentIdOverride.empty()) {
1684 RuntimeOption::DeploymentId = deploymentIdOverride;
1689 // Config ID
1690 Config::Bind(ConfigId, ini, config, "ConfigId", 0);
1691 auto configIdCounter = ServiceData::createCounter("vm.config.id");
1692 configIdCounter->setValue(ConfigId);
1696 // Logging
1697 auto setLogLevel = [](const std::string& value) {
1698 // ini parsing treats "None" as ""
1699 if (value == "None" || value == "") {
1700 Logger::LogLevel = Logger::LogNone;
1701 } else if (value == "Error") {
1702 Logger::LogLevel = Logger::LogError;
1703 } else if (value == "Warning") {
1704 Logger::LogLevel = Logger::LogWarning;
1705 } else if (value == "Info") {
1706 Logger::LogLevel = Logger::LogInfo;
1707 } else if (value == "Verbose") {
1708 Logger::LogLevel = Logger::LogVerbose;
1709 } else {
1710 return false;
1712 return true;
1714 auto str = Config::GetString(ini, config, "Log.Level");
1715 if (!str.empty()) {
1716 setLogLevel(str);
1718 IniSetting::Bind(IniSetting::CORE, IniSetting::PHP_INI_SYSTEM,
1719 "hhvm.log.level", IniSetting::SetAndGet<std::string>(
1720 setLogLevel,
1721 []() {
1722 switch (Logger::LogLevel) {
1723 case Logger::LogNone:
1724 return "None";
1725 case Logger::LogError:
1726 return "Error";
1727 case Logger::LogWarning:
1728 return "Warning";
1729 case Logger::LogInfo:
1730 return "Info";
1731 case Logger::LogVerbose:
1732 return "Verbose";
1734 return "";
1738 Config::Bind(Logger::UseLogFile, ini, config, "Log.UseLogFile", true);
1739 Config::Bind(LogFile, ini, config, "Log.File");
1740 Config::Bind(LogFileSymLink, ini, config, "Log.SymLink");
1741 Config::Bind(LogFilePeriodMultiplier, ini,
1742 config, "Log.PeriodMultiplier", 0);
1743 if (Logger::UseLogFile && RuntimeOption::ServerExecutionMode()) {
1744 RuntimeOption::ErrorLogs[Logger::DEFAULT] =
1745 ErrorLogFileData(LogFile, LogFileSymLink, LogFilePeriodMultiplier);
1747 if (Config::GetBool(ini, config, "Log.AlwaysPrintStackTraces")) {
1748 Logger::SetTheLogger(Logger::DEFAULT, new ExtendedLogger());
1749 ExtendedLogger::EnabledByDefault = true;
1752 Config::Bind(Logger::LogHeader, ini, config, "Log.Header");
1753 Config::Bind(Logger::LogNativeStackTrace, ini, config,
1754 "Log.NativeStackTrace", true);
1755 Config::Bind(Logger::UseSyslog, ini, config, "Log.UseSyslog", false);
1756 Config::Bind(Logger::UseRequestLog, ini, config, "Log.UseRequestLog",
1757 false);
1758 Config::Bind(Logger::AlwaysEscapeLog, ini, config, "Log.AlwaysEscapeLog",
1759 true);
1760 Config::Bind(Logger::UseCronolog, ini, config, "Log.UseCronolog", false);
1761 Config::Bind(Logger::MaxMessagesPerRequest, ini,
1762 config, "Log.MaxMessagesPerRequest", -1);
1763 Config::Bind(LogFileFlusher::DropCacheChunkSize, ini,
1764 config, "Log.DropCacheChunkSize", 1 << 20);
1765 Config::Bind(RuntimeOption::LogHeaderMangle, ini, config,
1766 "Log.HeaderMangle", 0);
1767 Config::Bind(AlwaysLogUnhandledExceptions, ini,
1768 config, "Log.AlwaysLogUnhandledExceptions",
1769 true);
1770 Config::Bind(NoSilencer, ini, config, "Log.NoSilencer");
1771 Config::Bind(RuntimeErrorReportingLevel, ini,
1772 config, "Log.RuntimeErrorReportingLevel",
1773 static_cast<int>(ErrorMode::HPHP_ALL));
1774 Config::Bind(ForceErrorReportingLevel, ini,
1775 config, "Log.ForceErrorReportingLevel", 0);
1776 Config::Bind(AccessLogDefaultFormat, ini, config,
1777 "Log.AccessLogDefaultFormat", "%h %l %u %t \"%r\" %>s %b");
1779 auto parseLogs = [] (const Hdf &config, const IniSetting::Map& ini,
1780 const std::string &name,
1781 std::map<std::string, AccessLogFileData> &logs) {
1782 auto parse_logs_callback = [&] (const IniSetting::Map &ini_pl,
1783 const Hdf &hdf_pl,
1784 const std::string &ini_pl_key) {
1785 string logName = hdf_pl.exists() && !hdf_pl.isEmpty()
1786 ? hdf_pl.getName()
1787 : ini_pl_key;
1788 string fname = Config::GetString(ini_pl, hdf_pl, "File", "", false);
1789 if (!fname.empty()) {
1790 string symlink = Config::GetString(ini_pl, hdf_pl, "SymLink", "",
1791 false);
1792 string format = Config::GetString(ini_pl, hdf_pl, "Format",
1793 AccessLogDefaultFormat, false);
1794 auto periodMultiplier = Config::GetUInt16(ini_pl, hdf_pl,
1795 "PeriodMultiplier",
1796 0, false);
1797 logs[logName] = AccessLogFileData(fname, symlink,
1798 format, periodMultiplier);
1803 Config::Iterate(parse_logs_callback, ini, config, name);
1806 parseLogs(config, ini, "Log.Access", AccessLogs);
1807 RPCLogs = AccessLogs;
1808 parseLogs(config, ini, "Log.RPC", RPCLogs);
1810 Config::Bind(AdminLogFormat, ini, config, "Log.AdminLog.Format",
1811 "%h %t %s %U");
1812 Config::Bind(AdminLogFile, ini, config, "Log.AdminLog.File");
1813 Config::Bind(AdminLogSymLink, ini, config, "Log.AdminLog.SymLink");
1816 // Error Handling
1818 Config::Bind(ErrorUpgradeLevel, ini, config, "ErrorHandling.UpgradeLevel",
1820 Config::Bind(MaxSerializedStringSize, ini,
1821 config, "ErrorHandling.MaxSerializedStringSize",
1822 64 * 1024 * 1024);
1823 Config::Bind(CallUserHandlerOnFatals, ini,
1824 config, "ErrorHandling.CallUserHandlerOnFatals", false);
1825 Config::Bind(ThrowExceptionOnBadMethodCall, ini,
1826 config, "ErrorHandling.ThrowExceptionOnBadMethodCall", true);
1827 Config::Bind(LogNativeStackOnOOM, ini,
1828 config, "ErrorHandling.LogNativeStackOnOOM", false);
1829 Config::Bind(NoticeFrequency, ini, config, "ErrorHandling.NoticeFrequency",
1831 Config::Bind(WarningFrequency, ini, config,
1832 "ErrorHandling.WarningFrequency", 1);
1835 // If we generated errors while loading RelativeConfigs report those now that
1836 // error reporting is initialized
1837 if (!relConfigsError.empty()) Logger::Error(relConfigsError);
1840 if (Config::GetInt64(ini, config, "ResourceLimit.CoreFileSizeOverride")) {
1841 setResourceLimit(RLIMIT_CORE, ini, config,
1842 "ResourceLimit.CoreFileSizeOverride");
1843 } else {
1844 setResourceLimit(RLIMIT_CORE, ini, config, "ResourceLimit.CoreFileSize");
1846 setResourceLimit(RLIMIT_NOFILE, ini, config, "ResourceLimit.MaxSocket");
1847 setResourceLimit(RLIMIT_DATA, ini, config, "ResourceLimit.RSS");
1848 // These don't have RuntimeOption::xxx bindings, but we still want to be
1849 // able to use ini_xxx functionality on them; so directly bind to a local
1850 // static via Config::Bind.
1851 static int64_t s_core_file_size_override, s_core_file_size, s_rss = 0;
1852 static int32_t s_max_socket = 0;
1853 Config::Bind(s_core_file_size_override, ini, config,
1854 "ResourceLimit.CoreFileSizeOverride", 0);
1855 Config::Bind(s_core_file_size, ini, config, "ResourceLimit.CoreFileSize",
1857 Config::Bind(s_max_socket, ini, config, "ResourceLimit.MaxSocket", 0);
1858 Config::Bind(s_rss, ini, config, "ResourceLimit.RSS", 0);
1860 Config::Bind(SocketDefaultTimeout, ini, config,
1861 "ResourceLimit.SocketDefaultTimeout", 60);
1862 Config::Bind(MaxSQLRowCount, ini, config, "ResourceLimit.MaxSQLRowCount",
1864 Config::Bind(SerializationSizeLimit, ini, config,
1865 "ResourceLimit.SerializationSizeLimit", StringData::MaxSize);
1866 Config::Bind(HeapSizeMB, ini, config, "ResourceLimit.HeapSizeMB",
1867 HeapSizeMB);
1868 Config::Bind(HeapResetCountBase, ini, config,
1869 "ResourceLimit.HeapResetCountBase", HeapResetCountBase);
1870 Config::Bind(HeapResetCountMultiple, ini, config,
1871 "ResourceLimit.HeapResetCountMultiple",
1872 HeapResetCountMultiple);
1873 Config::Bind(HeapLowWaterMark , ini, config,
1874 "ResourceLimit.HeapLowWaterMark", HeapLowWaterMark);
1875 Config::Bind(HeapHighWaterMark , ini, config,
1876 "ResourceLimit.HeapHighWaterMark",HeapHighWaterMark);
1879 // watchman
1880 Config::Bind(WatchmanRootSocket, ini, config, "watchman.socket.root", "");
1881 Config::Bind(WatchmanDefaultSocket, ini, config,
1882 "watchman.socket.default", "");
1885 // PHPisms
1886 Config::Bind(DisableCallUserFunc, ini, config,
1887 "Hack.Lang.Phpism.DisableCallUserFunc",
1888 DisableCallUserFunc);
1889 Config::Bind(DisableCallUserFuncArray, ini, config,
1890 "Hack.Lang.Phpism.DisableCallUserFuncArray",
1891 DisableCallUserFuncArray);
1892 Config::Bind(DisableNontoplevelDeclarations, ini, config,
1893 "Hack.Lang.Phpism.DisableNontoplevelDeclarations",
1894 DisableNontoplevelDeclarations);
1895 Config::Bind(DisableConstant, ini, config,
1896 "Hack.Lang.Phpism.DisableConstant",
1897 DisableConstant);
1900 // Repo
1901 auto repoModeToStr = [](RepoMode mode) {
1902 switch (mode) {
1903 case RepoMode::Closed:
1904 return "--";
1905 case RepoMode::ReadOnly:
1906 return "r-";
1907 case RepoMode::ReadWrite:
1908 return "rw";
1911 always_assert(false);
1912 return "";
1915 auto parseRepoMode = [&](const std::string& repoModeStr, const char* type, RepoMode defaultMode) {
1916 if (repoModeStr.empty()) {
1917 return defaultMode;
1919 if (repoModeStr == "--") {
1920 return RepoMode::Closed;
1922 if (repoModeStr == "r-") {
1923 return RepoMode::ReadOnly;
1925 if (repoModeStr == "rw") {
1926 return RepoMode::ReadWrite;
1929 Logger::Error("Bad config setting: Repo.%s.Mode=%s",
1930 type, repoModeStr.c_str());
1931 return RepoMode::ReadWrite;
1934 // Local Repo
1935 static std::string repoLocalMode;
1936 Config::Bind(repoLocalMode, ini, config, "Repo.Local.Mode", repoModeToStr(RepoLocalMode));
1937 RepoLocalMode = parseRepoMode(repoLocalMode, "Local", RepoMode::ReadOnly);
1939 // Repo.Path
1940 Config::Bind(RepoPath, ini, config, "Repo.Path", RepoPath);
1942 // Repo.Local.Path
1943 Config::Bind(RepoLocalPath, ini, config, "Repo.Local.Path");
1944 if (RepoLocalPath.empty()) {
1945 const char* HHVM_REPO_LOCAL_PATH = getenv("HHVM_REPO_LOCAL_PATH");
1946 if (HHVM_REPO_LOCAL_PATH != nullptr) {
1947 RepoLocalPath = HHVM_REPO_LOCAL_PATH;
1951 // Central Repo
1952 static std::string repoCentralMode;
1953 Config::Bind(repoCentralMode, ini, config, "Repo.Central.Mode", repoModeToStr(RepoCentralMode));
1954 RepoCentralMode = parseRepoMode(repoCentralMode, "Central", RepoMode::ReadWrite);
1956 // Repo.Central.Path
1957 Config::Bind(RepoCentralPath, ini, config, "Repo.Central.Path");
1958 Config::Bind(RepoCentralFileMode, ini, config, "Repo.Central.FileMode");
1959 Config::Bind(RepoCentralFileUser, ini, config, "Repo.Central.FileUser");
1960 Config::Bind(RepoCentralFileGroup, ini, config, "Repo.Central.FileGroup");
1962 Config::Bind(RepoAllowFallbackPath, ini, config, "Repo.AllowFallbackPath",
1963 RepoAllowFallbackPath);
1965 replacePlaceholders(RepoLocalPath);
1966 replacePlaceholders(RepoCentralPath);
1967 replacePlaceholders(RepoPath);
1969 Config::Bind(RepoJournal, ini, config, "Repo.Journal", RepoJournal);
1970 Config::Bind(RepoCommit, ini, config, "Repo.Commit",
1971 RepoCommit);
1972 Config::Bind(RepoDebugInfo, ini, config, "Repo.DebugInfo", RepoDebugInfo);
1973 Config::Bind(RepoLitstrLazyLoad, ini, config, "Repo.LitstrLazyLoad",
1974 RepoLitstrLazyLoad);
1975 Config::Bind(RepoAuthoritative, ini, config, "Repo.Authoritative",
1976 RepoAuthoritative);
1977 Config::Bind(RepoLocalReadaheadRate, ini, config,
1978 "Repo.LocalReadaheadRate", 0);
1979 Config::Bind(RepoLocalReadaheadConcurrent, ini, config,
1980 "Repo.LocalReadaheadConcurrent", false);
1981 Config::Bind(RepoBusyTimeoutMS, ini, config,
1982 "Repo.BusyTimeoutMS", RepoBusyTimeoutMS);
1984 if (RepoPath.empty()) {
1985 if (!RepoLocalPath.empty()) {
1986 RepoPath = RepoLocalPath;
1987 } else if (!RepoCentralPath.empty()) {
1988 RepoPath = RepoCentralPath;
1989 } else if (auto const env = getenv("HHVM_REPO_CENTRAL_PATH")) {
1990 RepoPath = env;
1991 replacePlaceholders(RepoPath);
1992 } else {
1993 always_assert_flog(
1994 !RepoAuthoritative,
1995 "Either Repo.Path, Repo.LocalPath, or Repo.CentralPath "
1996 "must be set in RepoAuthoritative mode"
2002 if (use_jemalloc) {
2003 // HHProf
2004 Config::Bind(HHProfEnabled, ini, config, "HHProf.Enabled", false);
2005 Config::Bind(HHProfActive, ini, config, "HHProf.Active", false);
2006 Config::Bind(HHProfAccum, ini, config, "HHProf.Accum", false);
2007 Config::Bind(HHProfRequest, ini, config, "HHProf.Request", false);
2010 // Eval
2011 Config::Bind(EnableHipHopSyntax, ini, config, "Eval.EnableHipHopSyntax",
2012 EnableHipHopSyntax);
2013 Config::Bind(EnableShortTags, ini, config, "Eval.EnableShortTags", true);
2014 Config::Bind(EnableXHP, ini, config, "Eval.EnableXHP", EnableXHP);
2015 Config::Bind(TimeoutsUseWallTime, ini, config, "Eval.TimeoutsUseWallTime",
2016 true);
2017 Config::Bind(CheckFlushOnUserClose, ini, config,
2018 "Eval.CheckFlushOnUserClose", true);
2019 Config::Bind(EvalInitialNamedEntityTableSize, ini, config,
2020 "Eval.InitialNamedEntityTableSize",
2021 EvalInitialNamedEntityTableSize);
2022 Config::Bind(EvalInitialStaticStringTableSize, ini, config,
2023 "Eval.InitialStaticStringTableSize",
2024 EvalInitialStaticStringTableSize);
2026 static std::string jitSerdesMode;
2027 Config::Bind(jitSerdesMode, ini, config, "Eval.JitSerdesMode", "Off");
2029 EvalJitSerdesMode = [&] {
2030 #define X(x) if (jitSerdesMode == #x) return JitSerdesMode::x
2031 X(Serialize);
2032 X(SerializeAndExit);
2033 X(Deserialize);
2034 X(DeserializeOrFail);
2035 X(DeserializeOrGenerate);
2036 X(DeserializeAndDelete);
2037 X(DeserializeAndExit);
2038 #undef X
2039 return JitSerdesMode::Off;
2040 }();
2041 Config::Bind(EvalJitSerdesFile, ini, config,
2042 "Eval.JitSerdesFile", EvalJitSerdesFile);
2043 // DumpPreciseProfileData defaults to true only when we can possibly write
2044 // profile data to disk. It can be set to false to avoid the performance
2045 // penalty of only running the interpreter during retranslateAll. We will
2046 // assume that DumpPreciseProfileData implies (JitSerdesMode::Serialize ||
2047 // JitSerdesMode::SerializeAndExit), to avoid checking too many flags in a
2048 // few places. The config file should never need to explicitly set
2049 // DumpPreciseProfileData to true.
2050 auto const couldDump = !EvalJitSerdesFile.empty() &&
2051 (isJitSerializing() ||
2052 (EvalJitSerdesMode == JitSerdesMode::DeserializeOrGenerate));
2053 Config::Bind(DumpPreciseProfData, ini, config,
2054 "Eval.DumpPreciseProfData", couldDump);
2055 Config::Bind(ProfDataTTLHours, ini, config,
2056 "Eval.ProfDataTTLHours", ProfDataTTLHours);
2057 Config::Bind(ProfDataTag, ini, config, "Eval.ProfDataTag", ProfDataTag);
2059 Config::Bind(CheckSymLink, ini, config, "Eval.CheckSymLink", true);
2060 Config::Bind(TrustAutoloaderPath, ini, config,
2061 "Eval.TrustAutoloaderPath", false);
2063 #define F(type, name, defaultVal) \
2064 Config::Bind(Eval ## name, ini, config, "Eval."#name, defaultVal);
2065 EVALFLAGS()
2066 #undef F
2068 if (EvalJitSerdesModeForceOff) EvalJitSerdesMode = JitSerdesMode::Off;
2069 if (!EvalEnableReusableTC) EvalReusableTCPadding = 0;
2070 if (numa_num_nodes <= 1) {
2071 EvalEnableNuma = false;
2074 Config::Bind(ServerForkEnabled, ini, config,
2075 "Server.Forking.Enabled", ServerForkEnabled);
2076 Config::Bind(ServerForkLogging, ini, config,
2077 "Server.Forking.LogForkAttempts", ServerForkLogging);
2078 if (!ServerForkEnabled && ServerExecutionMode()) {
2079 // Only use hugetlb pages when we don't fork().
2080 low_2m_pages(EvalMaxLowMemHugePages);
2081 high_2m_pages(EvalMaxHighArenaHugePages);
2083 #if USE_JEMALLOC_EXTENT_HOOKS
2084 g_useTHPUponHugeTLBFailure =
2085 Config::GetBool(ini, config, "Eval.UseTHPUponHugeTLBFailure",
2086 g_useTHPUponHugeTLBFailure);
2087 #endif
2088 s_enable_static_arena =
2089 Config::GetBool(ini, config, "Eval.UseTLStaticArena", true);
2091 replacePlaceholders(EvalEmbeddedDataExtractPath);
2092 replacePlaceholders(EvalEmbeddedDataFallbackPath);
2094 if (!jit::mcgen::retranslateAllEnabled()) {
2095 EvalJitWorkerThreads = 0;
2096 if (EvalJitSerdesMode != JitSerdesMode::Off) {
2097 if (ServerMode) {
2098 Logger::Warning("Eval.JitSerdesMode reset from " + jitSerdesMode +
2099 " to off, becasue JitRetranslateAll isn't enabled.");
2101 EvalJitSerdesMode = JitSerdesMode::Off;
2103 EvalJitSerdesFile.clear();
2104 DumpPreciseProfData = false;
2106 EvalJitPGOUseAddrCountedCheck &= addr_encodes_persistency;
2107 HardwareCounter::Init(EvalProfileHWEnable,
2108 url_decode(EvalProfileHWEvents.data(),
2109 EvalProfileHWEvents.size()).toCppString(),
2110 false,
2111 EvalProfileHWExcludeKernel,
2112 EvalProfileHWFastReads,
2113 EvalProfileHWExportInterval);
2115 Config::Bind(EnableIntrinsicsExtension, ini,
2116 config, "Eval.EnableIntrinsicsExtension",
2117 EnableIntrinsicsExtension);
2118 Config::Bind(RecordCodeCoverage, ini, config, "Eval.RecordCodeCoverage");
2119 if (EvalJit && RecordCodeCoverage) {
2120 throw std::runtime_error("Code coverage is not supported with "
2121 "Eval.Jit=true");
2123 Config::Bind(DisableSmallAllocator, ini, config,
2124 "Eval.DisableSmallAllocator", DisableSmallAllocator);
2125 SetArenaSlabAllocBypass(DisableSmallAllocator);
2126 EvalSlabAllocAlign = folly::nextPowTwo(EvalSlabAllocAlign);
2127 EvalSlabAllocAlign = std::min(EvalSlabAllocAlign,
2128 decltype(EvalSlabAllocAlign){4096});
2130 if (RecordCodeCoverage) CheckSymLink = true;
2131 Config::Bind(CodeCoverageOutputFile, ini, config,
2132 "Eval.CodeCoverageOutputFile");
2133 // NB: after we know the value of RepoAuthoritative.
2134 Config::Bind(EnableArgsInBacktraces, ini, config,
2135 "Eval.EnableArgsInBacktraces", !RepoAuthoritative);
2136 Config::Bind(EvalAuthoritativeMode, ini, config, "Eval.AuthoritativeMode",
2137 false);
2139 Config::Bind(CheckCLIClientCommands, ini, config, "Eval.CheckCLIClientCommands", 1);
2140 if (RepoAuthoritative) {
2141 EvalAuthoritativeMode = true;
2144 // Debugger (part of Eval)
2145 Config::Bind(EnableHphpdDebugger, ini, config,
2146 "Eval.Debugger.EnableDebugger");
2147 Config::Bind(EnableVSDebugger, ini, config,
2148 "Eval.Debugger.VSDebugEnable", EnableVSDebugger);
2149 Config::Bind(EnableDebuggerColor, ini, config,
2150 "Eval.Debugger.EnableDebuggerColor", true);
2151 Config::Bind(EnableDebuggerPrompt, ini, config,
2152 "Eval.Debugger.EnableDebuggerPrompt", true);
2153 Config::Bind(EnableDebuggerServer, ini, config,
2154 "Eval.Debugger.EnableDebuggerServer");
2155 Config::Bind(EnableDebuggerUsageLog, ini, config,
2156 "Eval.Debugger.EnableDebuggerUsageLog");
2157 Config::Bind(DebuggerServerIP, ini, config, "Eval.Debugger.IP");
2158 Config::Bind(DebuggerServerPort, ini, config, "Eval.Debugger.Port", 8089);
2159 Config::Bind(DebuggerDisableIPv6, ini, config,
2160 "Eval.Debugger.DisableIPv6", false);
2161 Config::Bind(DebuggerDefaultSandboxPath, ini, config,
2162 "Eval.Debugger.DefaultSandboxPath");
2163 Config::Bind(DebuggerStartupDocument, ini, config,
2164 "Eval.Debugger.StartupDocument");
2165 Config::Bind(DebuggerSignalTimeout, ini, config,
2166 "Eval.Debugger.SignalTimeout", 1);
2167 Config::Bind(DebuggerAuthTokenScriptBin, ini, config,
2168 "Eval.Debugger.Auth.TokenScriptBin");
2169 Config::Bind(DebuggerSessionAuthScriptBin, ini, config,
2170 "Eval.Debugger.Auth.SessionAuthScriptBin");
2174 // CodeCache
2175 using jit::CodeCache;
2176 Config::Bind(CodeCache::ASize, ini, config, "Eval.JitASize", 60 << 20);
2177 Config::Bind(CodeCache::AColdSize, ini, config, "Eval.JitAColdSize",
2178 24 << 20);
2179 Config::Bind(CodeCache::AFrozenSize, ini, config, "Eval.JitAFrozenSize",
2180 40 << 20);
2181 Config::Bind(CodeCache::ABytecodeSize, ini, config,
2182 "Eval.JitABytecodeSize", 0);
2183 Config::Bind(CodeCache::GlobalDataSize, ini, config,
2184 "Eval.JitGlobalDataSize", CodeCache::ASize >> 2);
2186 Config::Bind(CodeCache::MapTCHuge, ini, config, "Eval.MapTCHuge",
2187 hugePagesSoundNice());
2189 Config::Bind(CodeCache::TCNumHugeHotMB, ini, config,
2190 "Eval.TCNumHugeHotMB", 64);
2191 Config::Bind(CodeCache::TCNumHugeMainMB, ini, config,
2192 "Eval.TCNumHugeMainMB", 16);
2193 Config::Bind(CodeCache::TCNumHugeColdMB, ini, config,
2194 "Eval.TCNumHugeColdMB", 4);
2196 Config::Bind(CodeCache::AutoTCShift, ini, config, "Eval.JitAutoTCShift", 1);
2199 // Hack Language
2200 Config::Bind(CheckIntOverflow, ini, config,
2201 "Hack.Lang.CheckIntOverflow", 0);
2202 Config::Bind(StrictArrayFillKeys, ini, config,
2203 "Hack.Lang.StrictArrayFillKeys", HackStrictOption::ON);
2205 Config::Bind(LookForTypechecker, ini, config,
2206 "Hack.Lang.LookForTypechecker", false);
2208 // If you turn off LookForTypechecker, you probably want to turn this off
2209 // too -- basically, make the two look like the same option to external
2210 // users, unless you really explicitly want to set them differently for
2211 // some reason.
2212 Config::Bind(AutoTypecheck, ini, config, "Hack.Lang.AutoTypecheck",
2213 LookForTypechecker);
2214 Config::Bind(EnableClassLevelWhereClauses, ini, config,
2215 "Hack.Lang.EnableClassLevelWhereClauses",
2216 false);
2219 // Options for PHP7 features which break BC. (Features which do not break
2220 // BC don't need options here and can just always be turned on.)
2222 // NB that the "PHP7.all" option is intended to be only a master switch;
2223 // all runtime behavior gating should be based on sub-options (that's why
2224 // it's a file static not a static member of RuntimeOption). Also don't
2225 // forget to update mangleUnitPHP7Options if needed.
2227 // TODO: we may eventually want to make an option which specifies
2228 // directories or filenames to exclude from PHP7 behavior, and so checking
2229 // these may want to be per-file. We originally planned to do this from the
2230 // get-go, but threading that through turns out to be kind of annoying and
2231 // of questionable value, so just doing this for now.
2232 Config::Bind(s_PHP7_master, ini, config, "PHP7.all", s_PHP7_default);
2233 Config::Bind(PHP7_EngineExceptions, ini, config, "PHP7.EngineExceptions",
2234 s_PHP7_master);
2235 Config::Bind(PHP7_NoHexNumerics, ini, config, "PHP7.NoHexNumerics",
2236 s_PHP7_master);
2237 Config::Bind(PHP7_Builtins, ini, config, "PHP7.Builtins", s_PHP7_master);
2238 Config::Bind(PHP7_Substr, ini, config, "PHP7.Substr",
2239 s_PHP7_master);
2240 Config::Bind(PHP7_DisallowUnsafeCurlUploads, ini, config,
2241 "PHP7.DisallowUnsafeCurlUploads", s_PHP7_master);
2244 // Server
2245 Config::Bind(Host, ini, config, "Server.Host");
2246 Config::Bind(DefaultServerNameSuffix, ini, config,
2247 "Server.DefaultServerNameSuffix");
2248 Config::Bind(AlwaysDecodePostDataDefault, ini, config,
2249 "Server.AlwaysDecodePostDataDefault",
2250 AlwaysDecodePostDataDefault);
2251 Config::Bind(ServerType, ini, config, "Server.Type", ServerType);
2252 Config::Bind(ServerIP, ini, config, "Server.IP");
2253 Config::Bind(ServerFileSocket, ini, config, "Server.FileSocket");
2255 #ifdef FACEBOOK
2256 //Do not cause slowness on startup -- except for Facebook
2257 if (GetServerPrimaryIPv4().empty() && GetServerPrimaryIPv6().empty()) {
2258 throw std::runtime_error("Unable to resolve the server's "
2259 "IPv4 or IPv6 address");
2261 #endif
2263 Config::Bind(ServerPort, ini, config, "Server.Port", 80);
2264 Config::Bind(ServerBacklog, ini, config, "Server.Backlog", 128);
2265 Config::Bind(ServerConnectionLimit, ini, config,
2266 "Server.ConnectionLimit", 0);
2267 Config::Bind(ServerThreadCount, ini, config, "Server.ThreadCount",
2268 Process::GetCPUCount() * 2);
2269 Config::Bind(ServerQueueCount, ini, config, "Server.QueueCount",
2270 ServerThreadCount);
2271 Config::Bind(ServerIOThreadCount, ini, config,
2272 "Server.IOThreadCount", 1);
2273 Config::Bind(ServerLegacyBehavior, ini, config, "Server.LegacyBehavior",
2274 ServerLegacyBehavior);
2275 Config::Bind(ServerHugeThreadCount, ini, config,
2276 "Server.HugeThreadCount", 0);
2277 Config::Bind(ServerHugeStackKb, ini, config, "Server.HugeStackSizeKb", 384);
2278 ServerSchedPolicy =
2279 Config::GetInt32(ini, config, "Server.SchedPolicy", ServerSchedPolicy);
2280 ServerSchedPriority =
2281 Config::GetInt32(ini, config, "Server.SchedPriority", ServerSchedPriority);
2282 Config::Bind(ServerLoopSampleRate, ini, config,
2283 "Server.LoopSampleRate", 0);
2284 Config::Bind(ServerWarmupThrottleRequestCount, ini, config,
2285 "Server.WarmupThrottleRequestCount",
2286 ServerWarmupThrottleRequestCount);
2287 Config::Bind(ServerWarmupThrottleThreadCount, ini, config,
2288 "Server.WarmupThrottleThreadCount",
2289 Process::GetCPUCount());
2290 Config::Bind(ServerThreadDropCacheTimeoutSeconds, ini, config,
2291 "Server.ThreadDropCacheTimeoutSeconds", 0);
2292 if (Config::GetBool(ini, config, "Server.ThreadJobLIFO")) {
2293 ServerThreadJobLIFOSwitchThreshold = 0;
2295 Config::Bind(ServerThreadJobLIFOSwitchThreshold, ini, config,
2296 "Server.ThreadJobLIFOSwitchThreshold",
2297 ServerThreadJobLIFOSwitchThreshold);
2298 Config::Bind(ServerThreadJobMaxQueuingMilliSeconds, ini, config,
2299 "Server.ThreadJobMaxQueuingMilliSeconds", -1);
2300 Config::Bind(ServerThreadDropStack, ini, config, "Server.ThreadDropStack");
2301 Config::Bind(ServerHttpSafeMode, ini, config, "Server.HttpSafeMode");
2302 Config::Bind(ServerStatCache, ini, config, "Server.StatCache", false);
2303 Config::Bind(ServerFixPathInfo, ini, config, "Server.FixPathInfo", false);
2304 Config::Bind(ServerAddVaryEncoding, ini, config, "Server.AddVaryEncoding",
2305 ServerAddVaryEncoding);
2306 Config::Bind(ServerLogSettingsOnStartup, ini, config,
2307 "Server.LogSettingsOnStartup", false);
2308 Config::Bind(ServerLogReorderProps, ini, config,
2309 "Server.LogReorderProps", false);
2310 Config::Bind(ServerWarmupConcurrently, ini, config,
2311 "Server.WarmupConcurrently", false);
2312 Config::Bind(ServerDedupeWarmupRequests, ini, config,
2313 "Server.DedupeWarmupRequests", false);
2314 Config::Bind(ServerWarmupThreadCount, ini, config,
2315 "Server.WarmupThreadCount", ServerWarmupThreadCount);
2316 Config::Bind(ServerExtendedWarmupThreadCount, ini, config,
2317 "Server.ExtendedWarmup.ThreadCount",
2318 ServerExtendedWarmupThreadCount);
2319 Config::Bind(ServerExtendedWarmupDelaySeconds, ini, config,
2320 "Server.ExtendedWarmup.DelaySeconds",
2321 ServerExtendedWarmupDelaySeconds);
2322 Config::Bind(ServerExtendedWarmupRepeat, ini, config,
2323 "Server.ExtendedWarmup.Repeat", ServerExtendedWarmupRepeat);
2324 Config::Bind(ServerWarmupRequests, ini, config, "Server.WarmupRequests");
2325 Config::Bind(ServerExtendedWarmupRequests, ini, config,
2326 "Server.ExtendedWarmup.Requests");
2327 Config::Bind(ServerCleanupRequest, ini, config, "Server.CleanupRequest");
2328 Config::Bind(ServerInternalWarmupThreads, ini, config,
2329 "Server.InternalWarmupThreads", 0); // 0 = skip
2330 Config::Bind(ServerHighPriorityEndPoints, ini, config,
2331 "Server.HighPriorityEndPoints");
2332 Config::Bind(ServerExitOnBindFail, ini, config, "Server.ExitOnBindFail",
2333 false);
2335 Config::Bind(RequestTimeoutSeconds, ini, config,
2336 "Server.RequestTimeoutSeconds", 0);
2337 Config::Bind(MaxRequestAgeFactor, ini, config, "Server.MaxRequestAgeFactor",
2339 Config::Bind(PspTimeoutSeconds, ini, config, "Server.PspTimeoutSeconds", 0);
2340 Config::Bind(PspCpuTimeoutSeconds, ini, config,
2341 "Server.PspCpuTimeoutSeconds", 0);
2342 Config::Bind(RequestMemoryMaxBytes, ini, config,
2343 "Server.RequestMemoryMaxBytes", (16LL << 30)); // 16GiB
2344 RequestInfo::setOOMKillThreshold(
2345 Config::GetUInt64(ini, config, "Server.RequestMemoryOOMKillBytes",
2346 128ULL << 20));
2347 Config::Bind(RequestHugeMaxBytes, ini, config,
2348 "Server.RequestHugeMaxBytes", (24LL << 20));
2349 Config::Bind(ServerGracefulShutdownWait, ini,
2350 config, "Server.GracefulShutdownWait", 0);
2351 Config::Bind(ServerHarshShutdown, ini, config, "Server.HarshShutdown",
2352 true);
2353 Config::Bind(ServerKillOnTimeout, ini, config, "Server.KillOnTimeout",
2354 true);
2355 Config::Bind(ServerEvilShutdown, ini, config, "Server.EvilShutdown", true);
2356 Config::Bind(ServerPreShutdownWait, ini, config,
2357 "Server.PreShutdownWait", 0);
2358 Config::Bind(ServerShutdownListenWait, ini, config,
2359 "Server.ShutdownListenWait", 0);
2360 Config::Bind(ServerShutdownEOMWait, ini, config,
2361 "Server.ShutdownEOMWait", 0);
2362 Config::Bind(ServerPrepareToStopTimeout, ini, config,
2363 "Server.PrepareToStopTimeout", 240);
2364 Config::Bind(ServerPartialPostStatusCode, ini, config,
2365 "Server.PartialPostStatusCode", -1);
2366 Config::Bind(StopOldServer, ini, config, "Server.StopOld", false);
2367 Config::Bind(OldServerWait, ini, config, "Server.StopOldWait", 30);
2368 Config::Bind(ServerRSSNeededMb, ini, config, "Server.RSSNeededMb", 4096);
2369 Config::Bind(ServerCriticalFreeMb, ini, config,
2370 "Server.CriticalFreeMb", 512);
2371 Config::Bind(CacheFreeFactor, ini, config, "Server.CacheFreeFactor", 50);
2372 if (CacheFreeFactor > 100) CacheFreeFactor = 100;
2373 if (CacheFreeFactor < 0) CacheFreeFactor = 0;
2375 Config::Bind(ServerNextProtocols, ini, config, "Server.SSLNextProtocols");
2376 Config::Bind(ServerEnableH2C, ini, config, "Server.EnableH2C");
2377 extern bool g_brotliUseLocalArena;
2378 Config::Bind(g_brotliUseLocalArena, ini, config,
2379 "Server.BrotliUseLocalArena", g_brotliUseLocalArena);
2380 Config::Bind(BrotliCompressionEnabled, ini, config,
2381 "Server.BrotliCompressionEnabled", -1);
2382 Config::Bind(BrotliChunkedCompressionEnabled, ini, config,
2383 "Server.BrotliChunkedCompressionEnabled", -1);
2384 Config::Bind(BrotliCompressionLgWindowSize, ini, config,
2385 "Server.BrotliCompressionLgWindowSize", 20);
2386 Config::Bind(BrotliCompressionMode, ini, config,
2387 "Server.BrotliCompressionMode", 0);
2388 Config::Bind(BrotliCompressionQuality, ini, config,
2389 "Server.BrotliCompressionQuality", 6);
2390 Config::Bind(ZstdCompressionEnabled, ini, config,
2391 "Server.ZstdCompressionEnabled", -1);
2392 Config::Bind(ZstdCompressor::s_useLocalArena, ini, config,
2393 "Server.ZstdUseLocalArena", ZstdCompressor::s_useLocalArena);
2394 Config::Bind(ZstdCompressionLevel, ini, config,
2395 "Server.ZstdCompressionLevel", 3);
2396 Config::Bind(ZstdChecksumRate, ini, config,
2397 "Server.ZstdChecksumRate", 0);
2398 Config::Bind(GzipCompressionLevel, ini, config,
2399 "Server.GzipCompressionLevel", 3);
2400 Config::Bind(GzipMaxCompressionLevel, ini, config,
2401 "Server.GzipMaxCompressionLevel", 9);
2402 Config::Bind(GzipCompressor::s_useLocalArena, ini, config,
2403 "Server.GzipUseLocalArena", GzipCompressor::s_useLocalArena);
2404 Config::Bind(EnableKeepAlive, ini, config, "Server.EnableKeepAlive", true);
2405 Config::Bind(ExposeHPHP, ini, config, "Server.ExposeHPHP", true);
2406 Config::Bind(ExposeXFBServer, ini, config, "Server.ExposeXFBServer", false);
2407 Config::Bind(ExposeXFBDebug, ini, config, "Server.ExposeXFBDebug", false);
2408 Config::Bind(XFBDebugSSLKey, ini, config, "Server.XFBDebugSSLKey", "");
2409 Config::Bind(ConnectionTimeoutSeconds, ini, config,
2410 "Server.ConnectionTimeoutSeconds", -1);
2411 Config::Bind(EnableOutputBuffering, ini, config,
2412 "Server.EnableOutputBuffering");
2413 Config::Bind(OutputHandler, ini, config, "Server.OutputHandler");
2414 Config::Bind(ImplicitFlush, ini, config, "Server.ImplicitFlush");
2415 Config::Bind(EnableEarlyFlush, ini, config, "Server.EnableEarlyFlush",
2416 true);
2417 Config::Bind(ForceChunkedEncoding, ini, config,
2418 "Server.ForceChunkedEncoding");
2419 Config::Bind(MaxPostSize, ini, config, "Server.MaxPostSize", 100);
2420 MaxPostSize <<= 20;
2421 Config::Bind(AlwaysPopulateRawPostData, ini, config,
2422 "Server.AlwaysPopulateRawPostData", false);
2423 Config::Bind(TakeoverFilename, ini, config, "Server.TakeoverFilename");
2424 Config::Bind(ExpiresActive, ini, config, "Server.ExpiresActive", true);
2425 Config::Bind(ExpiresDefault, ini, config, "Server.ExpiresDefault", 2592000);
2426 if (ExpiresDefault < 0) ExpiresDefault = 2592000;
2427 Config::Bind(DefaultCharsetName, ini, config, "Server.DefaultCharsetName",
2428 "");
2429 Config::Bind(RequestBodyReadLimit, ini, config,
2430 "Server.RequestBodyReadLimit", -1);
2431 Config::Bind(EnableSSL, ini, config, "Server.EnableSSL");
2432 Config::Bind(SSLPort, ini, config, "Server.SSLPort", 443);
2433 Config::Bind(SSLCertificateFile, ini, config, "Server.SSLCertificateFile");
2434 Config::Bind(SSLCertificateKeyFile, ini, config,
2435 "Server.SSLCertificateKeyFile");
2436 Config::Bind(SSLCertificateDir, ini, config, "Server.SSLCertificateDir");
2437 Config::Bind(SSLTicketSeedFile, ini, config, "Server.SSLTicketSeedFile");
2438 Config::Bind(TLSDisableTLS1_2, ini, config, "Server.TLSDisableTLS1_2",
2439 false);
2440 Config::Bind(TLSClientCipherSpec, ini, config,
2441 "Server.TLSClientCipherSpec");
2442 Config::Bind(EnableSSLWithPlainText, ini, config,
2443 "Server.EnableSSLWithPlainText");
2444 Config::Bind(SSLClientAuthLevel, ini, config,
2445 "Server.SSLClientAuthLevel", 0);
2446 if (SSLClientAuthLevel < 0) SSLClientAuthLevel = 0;
2447 if (SSLClientAuthLevel > 2) SSLClientAuthLevel = 2;
2448 Config::Bind(SSLClientCAFile, ini, config, "Server.SSLClientCAFile", "");
2449 if (!SSLClientAuthLevel) {
2450 SSLClientCAFile = "";
2451 } else if (SSLClientCAFile.empty()) {
2452 throw std::runtime_error(
2453 "SSLClientCAFile is required to enable client auth");
2456 Config::Bind(ClientAuthAclIdentity, ini, config,
2457 "Server.ClientAuthAclIdentity", "");
2458 Config::Bind(ClientAuthAclAction, ini, config,
2459 "Server.ClientAuthAclAction", "");
2460 Config::Bind(ClientAuthFailClose, ini, config,
2461 "Server.ClientAuthFailClose", false);
2463 Config::Bind(ClientAuthLogSampleBase, ini, config,
2464 "Server.ClientAuthLogSampleBase", 100);
2465 if (ClientAuthLogSampleBase < 1) {
2466 ClientAuthLogSampleBase = 1;
2469 Config::Bind(SSLClientAuthLoggingSampleRatio, ini, config,
2470 "Server.SSLClientAuthLoggingSampleRatio", 0);
2471 if (SSLClientAuthLoggingSampleRatio < 0) {
2472 SSLClientAuthLoggingSampleRatio = 0;
2474 if (SSLClientAuthLoggingSampleRatio > ClientAuthLogSampleBase) {
2475 SSLClientAuthLoggingSampleRatio = ClientAuthLogSampleBase;
2478 Config::Bind(ClientAuthSuccessLogSampleRatio, ini, config,
2479 "Server.ClientAuthSuccessLogSampleRatio", 0);
2480 if (ClientAuthSuccessLogSampleRatio <
2481 SSLClientAuthLoggingSampleRatio) {
2482 ClientAuthSuccessLogSampleRatio = SSLClientAuthLoggingSampleRatio;
2484 if (ClientAuthSuccessLogSampleRatio > ClientAuthLogSampleBase) {
2485 ClientAuthSuccessLogSampleRatio = ClientAuthLogSampleBase;
2488 Config::Bind(ClientAuthFailureLogSampleRatio, ini, config,
2489 "Server.ClientAuthFailureLogSampleRatio", 0);
2490 if (ClientAuthFailureLogSampleRatio <
2491 SSLClientAuthLoggingSampleRatio) {
2492 ClientAuthFailureLogSampleRatio = SSLClientAuthLoggingSampleRatio;
2494 if (ClientAuthFailureLogSampleRatio > ClientAuthLogSampleBase) {
2495 ClientAuthFailureLogSampleRatio = ClientAuthLogSampleBase;
2498 // SourceRoot has been default to: Process::GetCurrentDirectory() + '/'
2499 auto defSourceRoot = SourceRoot;
2500 Config::Bind(SourceRoot, ini, config, "Server.SourceRoot", SourceRoot);
2501 SourceRoot = FileUtil::normalizeDir(SourceRoot);
2502 if (SourceRoot.empty()) {
2503 SourceRoot = defSourceRoot;
2505 FileCache::SourceRoot = SourceRoot;
2507 Config::Bind(IncludeSearchPaths, ini, config, "Server.IncludeSearchPaths");
2508 for (unsigned int i = 0; i < IncludeSearchPaths.size(); i++) {
2509 IncludeSearchPaths[i] = FileUtil::normalizeDir(IncludeSearchPaths[i]);
2511 IncludeSearchPaths.insert(IncludeSearchPaths.begin(), ".");
2513 Config::Bind(AutoloadEnabled, ini, config, "Autoload.Enabled", false);
2514 Config::Bind(AutoloadDBPath, ini, config, "Autoload.DB.Path");
2515 Config::Bind(AutoloadDBPerms, ini, config, "Autoload.DB.Perms", "0644");
2516 Config::Bind(AutoloadDBGroup, ini, config, "Autoload.DB.Group");
2517 Config::Bind(AutoloadLogging, ini, config, "Autoload.Logging",
2518 "hphp.runtime.ext.facts:=CRITICAL:slog;slog=hhvm");
2519 Config::Bind(AutoloadExcludedRepos, ini, config, "Autoload.ExcludedRepos");
2520 Config::Bind(AutoloadLoggingAllowPropagation, ini, config,
2521 "Autoload.AllowLoggingPropagation", false);
2522 Config::Bind(AutoloadEnforceOneDefinitionRule, ini, config,
2523 "Autoload.EnforceOneDefinitionRule", true);
2524 Config::Bind(AutoloadRethrowExceptions, ini, config,
2525 "Autoload.RethrowExceptions", true);
2527 Config::Bind(FileCache, ini, config, "Server.FileCache");
2528 Config::Bind(DefaultDocument, ini, config, "Server.DefaultDocument",
2529 "index.php");
2530 Config::Bind(GlobalDocument, ini, config, "Server.GlobalDocument");
2531 Config::Bind(ErrorDocument404, ini, config, "Server.ErrorDocument404");
2532 normalizePath(ErrorDocument404);
2533 Config::Bind(ForbiddenAs404, ini, config, "Server.ForbiddenAs404");
2534 Config::Bind(ErrorDocument500, ini, config, "Server.ErrorDocument500");
2535 normalizePath(ErrorDocument500);
2536 Config::Bind(FatalErrorMessage, ini, config, "Server.FatalErrorMessage");
2537 FontPath = FileUtil::normalizeDir(
2538 Config::GetString(ini, config, "Server.FontPath"));
2539 Config::Bind(EnableStaticContentFromDisk, ini, config,
2540 "Server.EnableStaticContentFromDisk", true);
2541 Config::Bind(EnableOnDemandUncompress, ini, config,
2542 "Server.EnableOnDemandUncompress", true);
2543 Config::Bind(EnableStaticContentMMap, ini, config,
2544 "Server.EnableStaticContentMMap", true);
2545 if (EnableStaticContentMMap) {
2546 EnableOnDemandUncompress = true;
2548 Config::Bind(Utf8izeReplace, ini, config, "Server.Utf8izeReplace", true);
2550 Config::Bind(RequestInitFunction, ini, config,
2551 "Server.RequestInitFunction");
2552 Config::Bind(RequestInitDocument, ini, config,
2553 "Server.RequestInitDocument");
2554 Config::Bind(SafeFileAccess, ini, config, "Server.SafeFileAccess");
2555 Config::Bind(AllowedDirectories, ini, config, "Server.AllowedDirectories");
2556 Config::Bind(WhitelistExec, ini, config, "Server.WhitelistExec");
2557 Config::Bind(WhitelistExecWarningOnly, ini, config,
2558 "Server.WhitelistExecWarningOnly");
2559 Config::Bind(AllowedExecCmds, ini, config, "Server.AllowedExecCmds");
2560 Config::Bind(UnserializationWhitelistCheck, ini, config,
2561 "Server.UnserializationWhitelistCheck", false);
2562 Config::Bind(UnserializationWhitelistCheckWarningOnly, ini, config,
2563 "Server.UnserializationWhitelistCheckWarningOnly", true);
2564 Config::Bind(UnserializationBigMapThreshold, ini, config,
2565 "Server.UnserializationBigMapThreshold", 1 << 16);
2566 Config::Bind(AllowedFiles, ini, config, "Server.AllowedFiles");
2567 Config::Bind(ForbiddenFileExtensions, ini, config,
2568 "Server.ForbiddenFileExtensions");
2569 Config::Bind(LockCodeMemory, ini, config, "Server.LockCodeMemory", false);
2570 Config::Bind(MaxArrayChain, ini, config, "Server.MaxArrayChain", INT_MAX);
2571 if (MaxArrayChain != INT_MAX) {
2572 // VanillaDict needs a higher threshold to avoid false-positives.
2573 // (and we always use VanillaDict)
2574 MaxArrayChain *= 2;
2577 Config::Bind(WarnOnCollectionToArray, ini, config,
2578 "Server.WarnOnCollectionToArray", false);
2579 Config::Bind(UseDirectCopy, ini, config, "Server.UseDirectCopy", false);
2580 Config::Bind(AlwaysUseRelativePath, ini, config,
2581 "Server.AlwaysUseRelativePath", false);
2583 // Server Upload
2584 Config::Bind(UploadMaxFileSize, ini, config,
2585 "Server.Upload.UploadMaxFileSize", 100);
2586 UploadMaxFileSize <<= 20;
2587 Config::Bind(UploadTmpDir, ini, config, "Server.Upload.UploadTmpDir",
2588 "/tmp");
2589 Config::Bind(EnableFileUploads, ini, config,
2590 "Server.Upload.EnableFileUploads", true);
2591 Config::Bind(MaxFileUploads, ini, config, "Server.Upload.MaxFileUploads",
2592 20);
2593 Config::Bind(EnableUploadProgress, ini, config,
2594 "Server.Upload.EnableUploadProgress");
2595 Config::Bind(Rfc1867Freq, ini, config, "Server.Upload.Rfc1867Freq",
2596 256 * 1024);
2597 if (Rfc1867Freq < 0) Rfc1867Freq = 256 * 1024;
2598 Config::Bind(Rfc1867Prefix, ini, config, "Server.Upload.Rfc1867Prefix",
2599 "vupload_");
2600 Config::Bind(Rfc1867Name, ini, config, "Server.Upload.Rfc1867Name",
2601 "video_ptoken");
2603 Config::Bind(ImageMemoryMaxBytes, ini, config,
2604 "Server.ImageMemoryMaxBytes", 0);
2605 if (ImageMemoryMaxBytes == 0) {
2606 ImageMemoryMaxBytes = UploadMaxFileSize * 2;
2608 Config::Bind(LightProcessFilePrefix, ini, config,
2609 "Server.LightProcessFilePrefix", "./lightprocess");
2610 Config::Bind(LightProcessCount, ini, config,
2611 "Server.LightProcessCount", 0);
2612 Config::Bind(LightProcess::g_strictUser, ini, config,
2613 "Server.LightProcessStrictUser", false);
2614 Config::Bind(ForceServerNameToHeader, ini, config,
2615 "Server.ForceServerNameToHeader");
2616 Config::Bind(PathDebug, ini, config, "Server.PathDebug", false);
2617 Config::Bind(ServerUser, ini, config, "Server.User", "");
2618 Config::Bind(AllowRunAsRoot, ini, config, "Server.AllowRunAsRoot", false);
2621 VirtualHost::SortAllowedDirectories(AllowedDirectories);
2623 auto vh_callback = [] (const IniSettingMap &ini_vh, const Hdf &hdf_vh,
2624 const std::string &ini_vh_key) {
2625 if (VirtualHost::IsDefault(ini_vh, hdf_vh, ini_vh_key)) {
2626 VirtualHost::GetDefault().init(ini_vh, hdf_vh, ini_vh_key);
2627 VirtualHost::GetDefault().addAllowedDirectories(AllowedDirectories);
2628 } else {
2629 auto host = std::make_shared<VirtualHost>(ini_vh, hdf_vh, ini_vh_key);
2630 host->addAllowedDirectories(AllowedDirectories);
2631 VirtualHosts.push_back(host);
2634 // Virtual Hosts have to be iterated in order. Because only the first
2635 // one that matches in the VirtualHosts vector gets applied and used.
2636 // Hdf's and ini (via Variant arrays) internal storage handles ordering
2637 // naturally (as specified top to bottom in the file and left to right on
2638 // the command line.
2639 Config::Iterate(vh_callback, ini, config, "VirtualHost");
2640 LowestMaxPostSize = VirtualHost::GetLowestMaxPostSize();
2643 // IpBlocks
2644 IpBlocks = std::make_shared<IpBlockMap>(ini, config);
2647 ReadSatelliteInfo(ini, config, SatelliteServerInfos,
2648 XboxPassword, XboxPasswords);
2651 // Xbox
2652 Config::Bind(XboxServerThreadCount, ini, config,
2653 "Xbox.ServerInfo.ThreadCount", 10);
2654 Config::Bind(XboxServerMaxQueueLength, ini, config,
2655 "Xbox.ServerInfo.MaxQueueLength", INT_MAX);
2656 if (XboxServerMaxQueueLength < 0) XboxServerMaxQueueLength = INT_MAX;
2657 Config::Bind(XboxServerInfoMaxRequest, ini, config,
2658 "Xbox.ServerInfo.MaxRequest", 500);
2659 Config::Bind(XboxServerInfoDuration, ini, config,
2660 "Xbox.ServerInfo.MaxDuration", 120);
2661 Config::Bind(XboxServerInfoReqInitFunc, ini, config,
2662 "Xbox.ServerInfo.RequestInitFunction", "");
2663 Config::Bind(XboxServerInfoReqInitDoc, ini, config,
2664 "Xbox.ServerInfo.RequestInitDocument", "");
2665 Config::Bind(XboxServerInfoAlwaysReset, ini, config,
2666 "Xbox.ServerInfo.AlwaysReset", false);
2667 Config::Bind(XboxServerLogInfo, ini, config, "Xbox.ServerInfo.LogInfo",
2668 false);
2669 Config::Bind(XboxProcessMessageFunc, ini, config, "Xbox.ProcessMessageFunc",
2670 "xbox_process_message");
2673 // Pagelet Server
2674 Config::Bind(PageletServerThreadCount, ini, config,
2675 "PageletServer.ThreadCount", 0);
2676 Config::Bind(PageletServerHugeThreadCount, ini, config,
2677 "PageletServer.HugeThreadCount", 0);
2678 Config::Bind(PageletServerThreadDropStack, ini, config,
2679 "PageletServer.ThreadDropStack");
2680 Config::Bind(PageletServerThreadDropCacheTimeoutSeconds, ini, config,
2681 "PageletServer.ThreadDropCacheTimeoutSeconds", 0);
2682 Config::Bind(PageletServerQueueLimit, ini, config,
2683 "PageletServer.QueueLimit", 0);
2686 // Static File
2688 hphp_string_imap<std::string> staticFileDefault;
2689 staticFileDefault["css"] = "text/css";
2690 staticFileDefault["gif"] = "image/gif";
2691 staticFileDefault["html"] = "text/html";
2692 staticFileDefault["jpeg"] = "image/jpeg";
2693 staticFileDefault["jpg"] = "image/jpeg";
2694 staticFileDefault["mp3"] = "audio/mpeg";
2695 staticFileDefault["png"] = "image/png";
2696 staticFileDefault["tif"] = "image/tiff";
2697 staticFileDefault["tiff"] = "image/tiff";
2698 staticFileDefault["txt"] = "text/plain";
2699 staticFileDefault["zip"] = "application/zip";
2701 Config::Bind(StaticFileExtensions, ini, config, "StaticFile.Extensions",
2702 staticFileDefault);
2704 auto matches_callback = [](const IniSettingMap& ini_m, const Hdf& hdf_m,
2705 const std::string& /*ini_m_key*/) {
2706 FilesMatches.push_back(std::make_shared<FilesMatch>(ini_m, hdf_m));
2708 Config::Iterate(matches_callback, ini, config, "StaticFile.FilesMatch");
2711 // PhpFile
2712 Config::Bind(PhpFileExtensions, ini, config, "PhpFile.Extensions");
2715 // Admin Server
2716 Config::Bind(AdminServerIP, ini, config, "AdminServer.IP", ServerIP);
2717 Config::Bind(AdminServerPort, ini, config, "AdminServer.Port", 0);
2718 Config::Bind(AdminThreadCount, ini, config, "AdminServer.ThreadCount", 1);
2719 Config::Bind(AdminServerEnableSSLWithPlainText, ini, config,
2720 "AdminServer.EnableSSLWithPlainText", false);
2721 Config::Bind(AdminServerStatsNeedPassword, ini, config,
2722 "AdminServer.StatsNeedPassword", AdminServerStatsNeedPassword);
2723 AdminPassword = Config::GetString(ini, config, "AdminServer.Password");
2724 AdminPasswords = Config::GetSet(ini, config, "AdminServer.Passwords");
2725 HashedAdminPasswords =
2726 Config::GetSet(ini, config, "AdminServer.HashedPasswords");
2727 Config::Bind(AdminDumpPath, ini, config,
2728 "AdminServer.DumpPath", "/tmp/hhvm_admin_dump");
2731 // Proxy
2732 Config::Bind(ProxyOriginRaw, ini, config, "Proxy.Origin");
2733 Config::Bind(ProxyPercentageRaw, ini, config, "Proxy.Percentage", 0);
2734 Config::Bind(ProxyRetry, ini, config, "Proxy.Retry", 3);
2735 Config::Bind(UseServeURLs, ini, config, "Proxy.ServeURLs");
2736 Config::Bind(ServeURLs, ini, config, "Proxy.ServeURLs");
2737 Config::Bind(UseProxyURLs, ini, config, "Proxy.ProxyURLs");
2738 Config::Bind(ProxyURLs, ini, config, "Proxy.ProxyURLs");
2739 Config::Bind(ProxyPatterns, ini, config, "Proxy.ProxyPatterns");
2742 // Http
2743 Config::Bind(HttpDefaultTimeout, ini, config, "Http.DefaultTimeout", 30);
2744 Config::Bind(HttpSlowQueryThreshold, ini, config, "Http.SlowQueryThreshold",
2745 5000);
2748 // Debug
2750 Config::Bind(NativeStackTrace, ini, config, "Debug.NativeStackTrace");
2751 StackTrace::Enabled = NativeStackTrace;
2752 Config::Bind(ServerErrorMessage, ini, config, "Debug.ServerErrorMessage");
2753 Config::Bind(RecordInput, ini, config, "Debug.RecordInput");
2754 Config::Bind(ClearInputOnSuccess, ini, config, "Debug.ClearInputOnSuccess",
2755 true);
2756 Config::Bind(ProfilerOutputDir, ini, config, "Debug.ProfilerOutputDir",
2757 "/tmp");
2758 Config::Bind(CoreDumpEmail, ini, config, "Debug.CoreDumpEmail");
2759 Config::Bind(CoreDumpReport, ini, config, "Debug.CoreDumpReport", true);
2760 if (CoreDumpReport) {
2761 install_crash_reporter();
2763 // Binding default dependenant on whether we are using an OSS build or
2764 // not, and that is set at initialization time of CoreDumpReportDirectory.
2765 Config::Bind(CoreDumpReportDirectory, ini, config,
2766 "Debug.CoreDumpReportDirectory", CoreDumpReportDirectory);
2767 std::ostringstream stack_trace_stream;
2768 stack_trace_stream << CoreDumpReportDirectory << "/stacktrace."
2769 << (int64_t)getpid() << ".log";
2770 StackTraceFilename = stack_trace_stream.str();
2772 Config::Bind(StackTraceTimeout, ini, config, "Debug.StackTraceTimeout", 0);
2773 Config::Bind(RemoteTraceOutputDir, ini, config,
2774 "Debug.RemoteTraceOutputDir", "/tmp");
2775 Config::Bind(TraceFunctions, ini, config,
2776 "Debug.TraceFunctions", TraceFunctions);
2779 // Stats
2780 Config::Bind(EnableStats, ini, config, "Stats.Enable",
2781 false); // main switch
2782 Config::Bind(EnableAPCStats, ini, config, "Stats.APC", false);
2783 Config::Bind(EnableWebStats, ini, config, "Stats.Web");
2784 Config::Bind(EnableMemoryStats, ini, config, "Stats.Memory");
2785 Config::Bind(EnableSQLStats, ini, config, "Stats.SQL");
2786 Config::Bind(EnableSQLTableStats, ini, config, "Stats.SQLTable");
2787 Config::Bind(EnableNetworkIOStatus, ini, config, "Stats.NetworkIO");
2788 Config::Bind(StatsXSL, ini, config, "Stats.XSL");
2789 Config::Bind(StatsXSLProxy, ini, config, "Stats.XSLProxy");
2790 Config::Bind(StatsSlotDuration, ini, config, "Stats.SlotDuration", 10 * 60);
2791 Config::Bind(StatsMaxSlot, ini, config, "Stats.MaxSlot",
2792 12 * 6); // 12 hours
2793 StatsSlotDuration = std::max(1u, StatsSlotDuration);
2794 StatsMaxSlot = std::max(2u, StatsMaxSlot);
2795 Config::Bind(EnableHotProfiler, ini, config, "Stats.EnableHotProfiler",
2796 true);
2797 Config::Bind(ProfilerTraceBuffer, ini, config, "Stats.ProfilerTraceBuffer",
2798 2000000);
2799 Config::Bind(ProfilerTraceExpansion, ini, config,
2800 "Stats.ProfilerTraceExpansion", 1.2);
2801 Config::Bind(ProfilerMaxTraceBuffer, ini, config,
2802 "Stats.ProfilerMaxTraceBuffer", 0);
2803 Config::Bind(TrackPerUnitMemory, ini, config,
2804 "Stats.TrackPerUnitMemory", false);
2807 Config::Bind(ServerVariables, ini, config, "ServerVariables");
2808 Config::Bind(EnvVariables, ini, config, "EnvVariables");
2811 // Sandbox
2812 Config::Bind(SandboxMode, ini, config, "Sandbox.SandboxMode");
2813 Config::Bind(SandboxPattern, ini, config, "Sandbox.Pattern");
2814 SandboxPattern = format_pattern(SandboxPattern, true);
2815 Config::Bind(SandboxHome, ini, config, "Sandbox.Home");
2816 Config::Bind(SandboxFallback, ini, config, "Sandbox.Fallback");
2817 Config::Bind(SandboxConfFile, ini, config, "Sandbox.ConfFile");
2818 Config::Bind(SandboxFromCommonRoot, ini, config, "Sandbox.FromCommonRoot");
2819 Config::Bind(SandboxDirectoriesRoot, ini, config,
2820 "Sandbox.DirectoriesRoot");
2821 Config::Bind(SandboxLogsRoot, ini, config, "Sandbox.LogsRoot");
2822 Config::Bind(SandboxServerVariables, ini, config,
2823 "Sandbox.ServerVariables");
2824 Config::Bind(SandboxDefaultUserFile, ini, config,
2825 "Sandbox.DefaultUserFile");
2826 Config::Bind(SandboxHostAlias, ini, config, "Sandbox.HostAlias");
2829 // Mail
2830 Config::Bind(SendmailPath, ini, config, "Mail.SendmailPath",
2831 "/usr/lib/sendmail -t -i");
2832 Config::Bind(MailForceExtraParameters, ini, config,
2833 "Mail.ForceExtraParameters");
2836 // Preg
2837 Config::Bind(PregBacktraceLimit, ini, config, "Preg.BacktraceLimit",
2838 1000000);
2839 Config::Bind(PregRecursionLimit, ini, config, "Preg.RecursionLimit",
2840 100000);
2841 Config::Bind(EnablePregErrorLog, ini, config, "Preg.ErrorLog", true);
2844 // SimpleXML
2845 Config::Bind(SimpleXMLEmptyNamespaceMatchesAll, ini, config,
2846 "SimpleXML.EmptyNamespaceMatchesAll", false);
2848 #ifdef FACEBOOK
2850 // Fb303Server
2851 Config::Bind(EnableFb303Server, ini, config, "Fb303Server.Enable",
2852 EnableFb303Server);
2853 Config::Bind(Fb303ServerPort, ini, config, "Fb303Server.Port", 0);
2854 Config::Bind(Fb303ServerIP, ini, config, "Fb303Server.IP");
2855 Config::Bind(Fb303ServerThreadStackSizeMb, ini, config,
2856 "Fb303Server.ThreadStackSizeMb", 8);
2857 Config::Bind(Fb303ServerWorkerThreads, ini, config,
2858 "Fb303Server.WorkerThreads", 1);
2859 Config::Bind(Fb303ServerPoolThreads, ini, config, "Fb303Server.PoolThreads",
2862 #endif
2865 // Xenon
2866 Config::Bind(XenonPeriodSeconds, ini, config, "Xenon.Period", 0.0);
2867 Config::Bind(XenonRequestFreq, ini, config, "Xenon.RequestFreq", 1);
2868 Config::Bind(XenonForceAlwaysOn, ini, config, "Xenon.ForceAlwaysOn", false);
2871 // Strobelight
2872 Config::Bind(StrobelightEnabled, ini, config, "Strobelight.Enabled", false);
2875 // Profiling
2876 Config::Bind(SetProfileNullThisObject, ini, config,
2877 "SetProfile.NullThisObject", true);
2880 // Loadhint queue penalty
2881 Config::Bind(ApplySecondaryQueuePenalty, ini, config, "Server.ApplySecondaryQueuePenalty", false);
2884 Config::Bind(TzdataSearchPaths, ini, config, "TzdataSearchPaths");
2886 Config::Bind(CustomSettings, ini, config, "CustomSettings");
2888 // Run initializers depedent on options, e.g., resizing atomic maps/vectors.
2889 refineStaticStringTableSize();
2890 InitFiniNode::ProcessPostRuntimeOptions();
2892 // **************************************************************************
2893 // DANGER
2895 // Do not bind any PHP_INI_ALL or PHP_INI_USER settings here! These settings
2896 // are process-wide, while those need to be thread-local since they are
2897 // per-request. They should go into RequestInjectionData. Getting this wrong
2898 // will cause subtle breakage -- in particular, it probably will not show up
2899 // in CLI mode, since everything there tends to be single theaded.
2901 // Per-dir INI settings are bound here, but that seems really questionable
2902 // since they can change per request too. TODO(#7757602) this should be
2903 // investigated.
2904 // **************************************************************************
2906 // Enables the hotfixing of a bug that occurred with D1797805 where
2907 // per request user settings (like upload_max_filesize) were not able to be
2908 // accessed on a server request any longer. The longer term fix is in review
2909 // D2099778, but we want that to simmer in Master for a while and we need
2910 // a hotfix for our current 3.6 LTS (Github Issue #4993)
2911 Config::Bind(EnableZendIniCompat, ini, config, "Eval.EnableZendIniCompat",
2912 true);
2913 // Language and Misc Configuration Options
2914 IniSetting::Bind(IniSetting::CORE, IniSetting::PHP_INI_ONLY, "expose_php",
2915 &RuntimeOption::ExposeHPHP);
2916 IniSetting::Bind(IniSetting::CORE, IniSetting::PHP_INI_PERDIR,
2917 "auto_prepend_file", &RuntimeOption::AutoPrependFile);
2918 IniSetting::Bind(IniSetting::CORE, IniSetting::PHP_INI_PERDIR,
2919 "auto_append_file", &RuntimeOption::AutoAppendFile);
2921 // Data Handling
2922 IniSetting::Bind(IniSetting::CORE, IniSetting::PHP_INI_PERDIR,
2923 "post_max_size",
2924 IniSetting::SetAndGet<int64_t>(
2925 nullptr,
2926 []() {
2927 return VirtualHost::GetMaxPostSize();
2930 &RuntimeOption::MaxPostSize);
2931 IniSetting::Bind(IniSetting::CORE, IniSetting::PHP_INI_PERDIR,
2932 "always_populate_raw_post_data",
2933 &RuntimeOption::AlwaysPopulateRawPostData);
2935 // Paths and Directories
2936 IniSetting::Bind(IniSetting::CORE, IniSetting::PHP_INI_SYSTEM,
2937 "doc_root", &RuntimeOption::SourceRoot);
2938 IniSetting::Bind(IniSetting::CORE, IniSetting::PHP_INI_SYSTEM,
2939 "sendmail_path", &RuntimeOption::SendmailPath);
2941 // FastCGI
2942 IniSetting::Bind(IniSetting::CORE, IniSetting::PHP_INI_ONLY,
2943 "pid", &RuntimeOption::PidFile);
2945 // File Uploads
2946 IniSetting::Bind(IniSetting::CORE, IniSetting::PHP_INI_SYSTEM,
2947 "file_uploads", "true",
2948 &RuntimeOption::EnableFileUploads);
2949 IniSetting::Bind(IniSetting::CORE, IniSetting::PHP_INI_SYSTEM,
2950 "upload_tmp_dir", &RuntimeOption::UploadTmpDir);
2951 IniSetting::Bind(IniSetting::CORE, IniSetting::PHP_INI_PERDIR,
2952 "upload_max_filesize",
2953 IniSetting::SetAndGet<std::string>(
2954 [](const std::string& value) {
2955 return ini_on_update(
2956 value, RuntimeOption::UploadMaxFileSize);
2958 []() {
2959 return convert_long_to_bytes(
2960 VirtualHost::GetUploadMaxFileSize());
2963 // Filesystem and Streams Configuration Options
2964 IniSetting::Bind(IniSetting::CORE, IniSetting::PHP_INI_SYSTEM,
2965 "allow_url_fopen",
2966 IniSetting::SetAndGet<std::string>(
2967 [](const std::string& /*value*/) { return false; },
2968 []() { return "1"; }));
2970 // HPHP specific
2971 IniSetting::Bind(IniSetting::CORE, IniSetting::PHP_INI_NONE,
2972 "hphp.compiler_id",
2973 IniSetting::SetAndGet<std::string>(
2974 [](const std::string& /*value*/) { return false; },
2975 []() { return compilerId().begin(); }));
2976 IniSetting::Bind(IniSetting::CORE, IniSetting::PHP_INI_NONE,
2977 "hphp.compiler_version",
2978 IniSetting::SetAndGet<std::string>(
2979 [](const std::string& /*value*/) { return false; },
2980 []() { return getHphpCompilerVersion(); }));
2981 IniSetting::Bind(IniSetting::CORE, IniSetting::PHP_INI_NONE,
2982 "hphp.cli_server_api_version",
2983 IniSetting::SetAndGet<uint64_t>(
2984 [](const uint64_t /*value*/) { return false; },
2985 []() { return cli_server_api_version(); }));
2986 IniSetting::Bind(
2987 IniSetting::CORE, IniSetting::PHP_INI_NONE, "hphp.build_id",
2988 IniSetting::SetAndGet<std::string>(
2989 [](const std::string& /*value*/) { return false; }, nullptr),
2990 &RuntimeOption::BuildId);
2991 IniSetting::Bind(IniSetting::CORE, IniSetting::PHP_INI_SYSTEM,
2992 "notice_frequency",
2993 &RuntimeOption::NoticeFrequency);
2994 IniSetting::Bind(IniSetting::CORE, IniSetting::PHP_INI_SYSTEM,
2995 "warning_frequency",
2996 &RuntimeOption::WarningFrequency);
2997 IniSetting::Bind(IniSetting::CORE, IniSetting::PHP_INI_ONLY,
2998 "hhvm.build_type",
2999 IniSetting::SetAndGet<std::string>(
3000 [](const std::string&) {
3001 return false;
3003 []() {
3004 return s_hhvm_build_type.c_str();
3008 // Extensions
3009 Config::Bind(RuntimeOption::ExtensionDir, ini, config, "extension_dir",
3010 RuntimeOption::ExtensionDir, false);
3011 Config::Bind(RuntimeOption::DynamicExtensionPath, ini,
3012 config, "DynamicExtensionPath",
3013 RuntimeOption::DynamicExtensionPath);
3014 Config::Bind(RuntimeOption::Extensions, ini, config, "extensions");
3015 Config::Bind(RuntimeOption::DynamicExtensions, ini,
3016 config, "DynamicExtensions");
3018 ExtensionRegistry::moduleLoad(ini, config);
3019 initialize_apc();
3021 if (TraceFunctions.size()) Trace::ensureInit(getTraceOutputFile());
3023 if (RO::EvalJitEnableRenameFunction && RO::RepoAuthoritative) {
3024 throw std::runtime_error("Can't use Eval.JitEnableRenameFunction if "
3025 " RepoAuthoritative is turned on");
3028 // Bespoke array-likes
3030 auto const enable_logging = RO::EvalBespokeArrayLikeMode != 0;
3031 bespoke::setLoggingEnabled(enable_logging);
3032 specializeVanillaDestructors();
3034 // Coeffects
3035 CoeffectsConfig::init(RO::EvalCoeffectEnforcementLevels);
3036 RuntimeOption::EvalPureVerifyBody = std::max(
3037 RuntimeOption::EvalPureVerifyBody, RuntimeOption::EvalRxVerifyBody);
3039 // Initialize defaults for repo-specific parser configuration options.
3040 RepoOptions::setDefaults(config, ini);
3042 // Start profiling RDS, if enabled. We'll stop when we hit retranslateAll.
3043 if (rds::shouldProfileAccesses()) rds::startProfiling();
3046 ///////////////////////////////////////////////////////////////////////////////
3048 uintptr_t lowArenaMinAddr() {
3049 const char* str = getenv("HHVM_LOW_ARENA_START");
3050 if (str == nullptr) return 1u << 30;
3051 uintptr_t start = 0;
3052 if (sscanf(str, "0x%lx", &start) == 1) return start;
3053 if (sscanf(str, "%lu", &start) == 1) return start;
3054 fprintf(stderr, "Bad environment variable HHVM_LOW_ARENA_START: %s\n", str);
3055 abort();
3058 ///////////////////////////////////////////////////////////////////////////////