Make comparison IR ops layout agnostic
[hiphop-php.git] / hphp / runtime / base / runtime-option.cpp
blob62f2643939b35565893de069fb9960318a50909c
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/apc-file-storage.h"
21 #include "hphp/runtime/base/autoload-handler.h"
22 #include "hphp/runtime/base/bespoke-array.h"
23 #include "hphp/runtime/base/builtin-functions.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/request-info.h"
35 #include "hphp/runtime/base/static-string-table.h"
36 #include "hphp/runtime/base/tv-refcount.h"
37 #include "hphp/runtime/base/zend-url.h"
38 #include "hphp/runtime/ext/extension-registry.h"
39 #include "hphp/runtime/server/access-log.h"
40 #include "hphp/runtime/server/cli-server.h"
41 #include "hphp/runtime/server/files-match.h"
42 #include "hphp/runtime/server/satellite-server.h"
43 #include "hphp/runtime/server/virtual-host.h"
44 #include "hphp/runtime/vm/jit/code-cache.h"
45 #include "hphp/runtime/vm/jit/mcgen-translate.h"
46 #include "hphp/runtime/vm/treadmill.h"
47 #include "hphp/util/arch.h"
48 #include "hphp/util/atomic-vector.h"
49 #include "hphp/util/build-info.h"
50 #include "hphp/util/cpuid.h"
51 #include "hphp/util/current-executable.h" // @donotremove
52 #include "hphp/util/file-cache.h"
53 #include "hphp/util/gzip.h"
54 #include "hphp/util/hardware-counter.h"
55 #include "hphp/util/hdf.h"
56 #include "hphp/util/log-file-flusher.h"
57 #include "hphp/util/logger.h"
58 #include "hphp/util/network.h"
59 #include "hphp/util/numa.h"
60 #include "hphp/util/process.h"
61 #include "hphp/util/service-data.h"
62 #include "hphp/util/stack-trace.h"
63 #include "hphp/util/text-util.h"
64 #include "hphp/util/zstd.h"
65 #include "hphp/zend/zend-string.h"
67 #include <cstdint>
68 #include <limits>
69 #include <map>
70 #include <memory>
71 #include <set>
72 #include <stdexcept>
73 #include <vector>
75 #include <boost/algorithm/string/predicate.hpp>
76 #include <folly/CPortability.h>
77 #include <folly/FileUtil.h>
78 #include <folly/String.h>
79 #include <folly/portability/SysResource.h>
80 #include <folly/portability/SysTime.h>
81 #include <folly/portability/Unistd.h>
83 #if defined (__linux__) && defined (__aarch64__)
84 #include <sys/auxv.h>
85 #include <asm/hwcap.h>
86 #endif
88 #ifdef __APPLE__
89 #define st_mtim st_mtimespec
90 #define st_ctim st_ctimespec
91 #endif
93 namespace HPHP {
94 ///////////////////////////////////////////////////////////////////////////////
96 bool RepoOptions::s_init{false};
97 RepoOptions RepoOptions::s_defaults;
99 namespace {
101 #ifdef FACEBOOK
102 const static bool s_PHP7_default = false;
103 #else
104 const static bool s_PHP7_default = true;
105 #endif
106 // PHP7 is off by default (false). s_PHP7_master is not a static member of
107 // RuntimeOption so that it's private to this file and not exposed -- it's a
108 // master switch only, and not to be used for any actual gating, use the more
109 // granular options instead. (It can't be a local since Config::Bind will take
110 // and store a pointer to it.)
111 static bool s_PHP7_master = s_PHP7_default;
113 std::vector<std::string> s_RelativeConfigs;
115 ////////////////////////////////////////////////////////////////////////////////
117 char mangleForKey(bool b) { return b ? '1' : '0'; }
118 std::string mangleForKey(const RepoOptions::StringMap& map) {
119 std::string s;
120 s += folly::to<std::string>(map.size());
121 s += '\0';
122 for (auto& par : map) {
123 s += par.first + '\0' + par.second + '\0';
125 return s;
127 std::string mangleForKey(std::string s) { return s; }
128 void hdfExtract(const Hdf& hdf, const char* name, bool& val, bool dv) {
129 val = hdf[name].configGetBool(dv);
131 void hdfExtract(const Hdf& hdf, const char* name, uint16_t& val, uint16_t dv) {
132 val = hdf[name].configGetUInt16(dv);
134 void hdfExtract(
135 const Hdf& hdf,
136 const char* name,
137 RepoOptions::StringMap& map,
138 const RepoOptions::StringMap& dv
140 Hdf config = hdf[name];
141 if (config.exists() && !config.isEmpty()) config.configGet(map);
142 else map = dv;
144 void hdfExtract(
145 const Hdf& hdf,
146 const char* name,
147 std::string& val,
148 std::string dv
150 val = hdf[name].configGetString(dv);
152 folly::dynamic toIniValue(bool b) {
153 return b ? "1" : "0";
156 folly::dynamic toIniValue(const RepoOptions::StringMap& map) {
157 folly::dynamic obj = folly::dynamic::object();
158 for (auto& kv : map) {
159 obj[kv.first] = kv.second;
161 return obj;
164 folly::dynamic toIniValue(const std::string& str) {
165 return str;
168 struct CachedRepoOptions {
169 CachedRepoOptions() = default;
170 explicit CachedRepoOptions(RepoOptions&& opts)
171 : options(new RepoOptions(std::move(opts)))
173 CachedRepoOptions(const CachedRepoOptions& opts)
174 : options(nullptr)
176 if (auto o = opts.options.load(std::memory_order_relaxed)) {
177 options.store(new RepoOptions(*o), std::memory_order_relaxed);
180 ~CachedRepoOptions() {
181 Treadmill::enqueue([opt = options.exchange(nullptr)] { delete opt; });
184 CachedRepoOptions& operator=(const CachedRepoOptions& opts) {
185 auto const o = opts.options.load(std::memory_order_relaxed);
186 auto const old = options.exchange(o ? new RepoOptions(*o) : nullptr);
187 if (old) Treadmill::enqueue([old] { delete old; });
188 return *this;
191 static bool isChanged(const RepoOptions* opts, struct stat s) {
192 auto const o = opts->stat();
193 return
194 s.st_mtim.tv_sec != o.st_mtim.tv_sec ||
195 s.st_mtim.tv_nsec != o.st_mtim.tv_nsec ||
196 s.st_ctim.tv_sec != o.st_ctim.tv_sec ||
197 s.st_ctim.tv_nsec != o.st_ctim.tv_nsec ||
198 s.st_dev != o.st_dev ||
199 s.st_ino != o.st_ino;
202 const RepoOptions* update(RepoOptions&& opts) const {
203 auto const val = new RepoOptions(std::move(opts));
204 auto const old = options.exchange(val);
205 if (old) Treadmill::enqueue([old] { delete old; });
206 return val;
209 const RepoOptions* fetch(struct stat st) const {
210 auto const opts = options.load(std::memory_order_relaxed);
211 return opts && !isChanged(opts, st) ? opts : nullptr;
214 mutable std::atomic<RepoOptions*> options{nullptr};
217 using RepoOptionCache = tbb::concurrent_hash_map<
218 std::string,
219 CachedRepoOptions,
220 stringHashCompare
222 RepoOptionCache s_repoOptionCache;
224 template<class F>
225 bool walkDirTree(std::string fpath, F func) {
226 const char* filename = ".hhvmconfig.hdf";
227 do {
228 auto const off = fpath.rfind('/');
229 if (off == std::string::npos) return false;
230 fpath.resize(off);
231 fpath += '/';
232 fpath += filename;
234 if (func(fpath)) return true;
236 fpath.resize(off);
237 } while (!fpath.empty() && fpath != "/");
238 return false;
241 RDS_LOCAL(std::string, s_lastSeenRepoConfig);
245 const RepoOptions& RepoOptions::forFile(const char* path) {
246 if (!RuntimeOption::EvalEnablePerRepoOptions) return defaults();
248 std::string fpath{path};
249 if (boost::starts_with(fpath, "/:")) return defaults();
251 // Fast path: we have an active request and it has cached a RepoOptions
252 // which has not been modified. This only works when the runtime option
253 // Eval.FatalOnParserOptionMismatch is set. It can cause us to miss out on
254 // configs that were added between the current directory and the source file.
255 // (Loading these configs would result in a fatal anyway with this option)
256 if (!g_context.isNull()) {
257 if (auto const opts = g_context->getRepoOptionsForRequest()) {
258 // If path() is empty we have the default() options, which means we have
259 // negatively cached the existance of a .hhvmconfig.hdf for this request.
260 if (opts->path().empty()) return *opts;
262 if (boost::starts_with(fpath, opts->path())) {
263 struct stat st;
264 if (lstat(opts->path().data(), &st) == 0) {
265 if (!CachedRepoOptions::isChanged(opts, st)) return *opts;
271 auto const set = [&] (
272 RepoOptionCache::const_accessor& rpathAcc,
273 const std::string& path,
274 const struct stat& st
275 ) -> const RepoOptions* {
276 *s_lastSeenRepoConfig = path;
277 if (auto const opts = rpathAcc->second.fetch(st)) {
278 return opts;
280 RepoOptions newOpts{path.data()};
281 newOpts.m_stat = st;
282 return rpathAcc->second.update(std::move(newOpts));
285 auto const test = [&] (const std::string& path) -> const RepoOptions* {
286 struct stat st;
287 RepoOptionCache::const_accessor rpathAcc;
288 if (!s_repoOptionCache.find(rpathAcc, path)) return nullptr;
289 if (lstat(path.data(), &st) != 0) {
290 s_repoOptionCache.erase(rpathAcc);
291 return nullptr;
293 return set(rpathAcc, path, st);
296 const RepoOptions* ret{nullptr};
298 // WARNING: when Eval.CachePerRepoOptionsPath we cache the last used path for
299 // RepoOptions per thread, and while we will detect changes to this
300 // file, and do a rescan in the event that it is deleted or doesn't
301 // match the current file being loaded, we will miss out on new
302 // configs that may be added. Since we expect to see a single config
303 // per repository we expect that this will be a reasonably safe,
304 // optimization.
305 if (RuntimeOption::EvalCachePerRepoOptionsPath) {
306 if (!s_lastSeenRepoConfig->empty() &&
307 boost::starts_with(fpath, *s_lastSeenRepoConfig)) {
308 if (auto const r = test(*s_lastSeenRepoConfig)) return *r;
309 s_lastSeenRepoConfig->clear();
312 // If the last seen path isn't set yet or is no longer accurate try checking
313 // other cached paths before falling back to the filesystem.
314 walkDirTree(fpath, [&] (const std::string& path) {
315 return (ret = test(path)) != nullptr;
319 if (ret) return *ret;
321 walkDirTree(fpath, [&] (const std::string& path) {
322 struct stat st;
323 if (lstat(path.data(), &st) != 0) return false;
324 RepoOptionCache::const_accessor rpathAcc;
325 s_repoOptionCache.insert(rpathAcc, path);
326 ret = set(rpathAcc, path, st);
327 return true;
330 return ret ? *ret : defaults();
333 std::string RepoOptions::cacheKeyRaw() const {
334 return std::string("")
335 #define N(_, n, ...) + mangleForKey(n)
336 #define P(_, n, ...) + mangleForKey(n)
337 #define H(_, n, ...) + mangleForKey(n)
338 #define E(_, n, ...) + mangleForKey(n)
339 PARSERFLAGS()
340 AUTOLOADFLAGS();
341 #undef N
342 #undef P
343 #undef H
344 #undef E
347 std::string RepoOptions::cacheKeySha1() const {
348 return string_sha1(cacheKeyRaw());
351 std::string RepoOptions::toJSON() const {
352 return folly::toJson(toDynamic());
355 folly::dynamic RepoOptions::toDynamic() const {
356 folly::dynamic json = folly::dynamic::object();
357 #define OUT(key, var) \
359 auto const ini_name = Config::IniName(key); \
360 auto const ini_value = toIniValue(var); \
361 folly::dynamic entry = folly::dynamic::object(); \
362 entry["global_value"] = ini_value; \
363 entry["local_value"] = ini_value; \
364 entry["access"] = 4; \
365 json[ini_name] = entry; \
368 #define N(_, n, ...) OUT(#n, n)
369 #define P(_, n, ...) OUT("PHP7." #n, n)
370 #define H(_, n, ...) OUT("Hack.Lang." #n, n)
371 #define E(_, n, ...) OUT("Eval." #n, n)
372 PARSERFLAGS()
373 AUTOLOADFLAGS();
374 #undef N
375 #undef P
376 #undef H
377 #undef E
379 #undef OUT
381 return json;
384 bool RepoOptions::operator==(const RepoOptions& o) const {
385 #define N(_, n, ...) if (n != o.n) return false;
386 #define P(_, n, ...) if (n != o.n) return false;
387 #define H(_, n, ...) if (n != o.n) return false;
388 #define E(_, n, ...) if (n != o.n) return false;
389 PARSERFLAGS()
390 AUTOLOADFLAGS();
391 #undef N
392 #undef P
393 #undef H
394 #undef E
395 return true;
398 const RepoOptions& RepoOptions::defaults() {
399 always_assert(s_init);
400 return s_defaults;
403 void RepoOptions::filterNamespaces() {
404 for (auto it = AliasedNamespaces.begin(); it != AliasedNamespaces.end(); ) {
405 if (!is_valid_class_name(it->second)) {
406 Logger::Warning("Skipping invalid AliasedNamespace %s\n",
407 it->second.c_str());
408 it = AliasedNamespaces.erase(it);
409 continue;
412 while (it->second.size() && it->second[0] == '\\') {
413 it->second = it->second.substr(1);
416 ++it;
420 RepoOptions::RepoOptions(const char* file) : m_path(file) {
421 always_assert(s_init);
422 Hdf config{file};
423 Hdf parserConfig = config["Parser"];
425 #define N(_, n, ...) hdfExtract(parserConfig, #n, n, s_defaults.n);
426 #define P(_, n, ...) hdfExtract(parserConfig, "PHP7." #n, n, s_defaults.n);
427 #define H(_, n, ...) hdfExtract(parserConfig, "Hack.Lang." #n, n, s_defaults.n);
428 #define E(_, n, ...) hdfExtract(parserConfig, "Eval." #n, n, s_defaults.n);
429 PARSERFLAGS();
430 #undef N
431 #undef P
432 #undef H
433 #undef E
435 Hdf autoloadConfig = config["Autoload"];
436 #define N(_, n, ...) hdfExtract(autoloadConfig, #n, n, s_defaults.n);
437 #define P(_, n, ...) hdfExtract(autoloadConfig, "PHP7." #n, n, s_defaults.n);
438 #define H(_, n, ...) hdfExtract(autoloadConfig, "Hack.Lang." #n, n, \
439 s_defaults.n);
440 #define E(_, n, ...) hdfExtract(autoloadConfig, "Eval." #n, n, s_defaults.n);
441 AUTOLOADFLAGS();
442 #undef N
443 #undef P
444 #undef H
445 #undef E
447 filterNamespaces();
450 void RepoOptions::initDefaults(const Hdf& hdf, const IniSettingMap& ini) {
451 #define N(_, n, dv) Config::Bind(n, ini, hdf, #n, dv);
452 #define P(_, n, dv) Config::Bind(n, ini, hdf, "PHP7." #n, dv);
453 #define H(_, n, dv) Config::Bind(n, ini, hdf, "Hack.Lang." #n, dv);
454 #define E(_, n, dv) Config::Bind(n, ini, hdf, "Eval." #n, dv);
455 PARSERFLAGS()
456 AUTOLOADFLAGS()
457 #undef N
458 #undef P
459 #undef H
460 #undef E
462 filterNamespaces();
463 m_path.clear();
466 void RepoOptions::setDefaults(const Hdf& hdf, const IniSettingMap& ini) {
467 always_assert(!s_init);
468 s_defaults.initDefaults(hdf, ini);
469 s_init = true;
472 ///////////////////////////////////////////////////////////////////////////////
474 std::string RuntimeOption::BuildId;
475 std::string RuntimeOption::InstanceId;
476 std::string RuntimeOption::DeploymentId;
477 int64_t RuntimeOption::ConfigId = 0;
478 std::string RuntimeOption::PidFile = "www.pid";
480 bool RuntimeOption::ServerMode = false;
482 bool RuntimeOption::EnableHipHopSyntax = true;
483 bool RuntimeOption::EnableShortTags = true;
484 bool RuntimeOption::EnableXHP = true;
485 bool RuntimeOption::EnableIntrinsicsExtension = false;
486 bool RuntimeOption::CheckSymLink = true;
487 bool RuntimeOption::TrustAutoloaderPath = false;
488 bool RuntimeOption::EnableArgsInBacktraces = true;
489 bool RuntimeOption::EnableZendIniCompat = true;
490 bool RuntimeOption::TimeoutsUseWallTime = true;
491 bool RuntimeOption::CheckFlushOnUserClose = true;
492 bool RuntimeOption::EvalAuthoritativeMode = false;
493 bool RuntimeOption::DumpPreciseProfData = true;
494 uint32_t RuntimeOption::EvalInitialStaticStringTableSize =
495 kDefaultInitialStaticStringTableSize;
496 uint32_t RuntimeOption::EvalInitialNamedEntityTableSize = 30000;
497 JitSerdesMode RuntimeOption::EvalJitSerdesMode{};
498 int RuntimeOption::ProfDataTTLHours = 24;
499 std::string RuntimeOption::ProfDataTag;
500 std::string RuntimeOption::EvalJitSerdesFile;
502 std::map<std::string, ErrorLogFileData> RuntimeOption::ErrorLogs = {
503 {Logger::DEFAULT, ErrorLogFileData()},
505 // these hold the DEFAULT logger
506 std::string RuntimeOption::LogFile;
507 std::string RuntimeOption::LogFileSymLink;
508 uint16_t RuntimeOption::LogFilePeriodMultiplier;
510 int RuntimeOption::LogHeaderMangle = 0;
511 bool RuntimeOption::AlwaysLogUnhandledExceptions = true;
512 bool RuntimeOption::AlwaysEscapeLog = true;
513 bool RuntimeOption::NoSilencer = false;
514 int RuntimeOption::ErrorUpgradeLevel = 0;
515 bool RuntimeOption::CallUserHandlerOnFatals = false;
516 bool RuntimeOption::ThrowExceptionOnBadMethodCall = true;
517 bool RuntimeOption::LogNativeStackOnOOM = true;
518 int RuntimeOption::RuntimeErrorReportingLevel =
519 static_cast<int>(ErrorMode::HPHP_ALL);
520 int RuntimeOption::ForceErrorReportingLevel = 0;
522 std::string RuntimeOption::ServerUser;
523 std::vector<std::string> RuntimeOption::TzdataSearchPaths;
525 int RuntimeOption::MaxSerializedStringSize = 64 * 1024 * 1024; // 64MB
526 bool RuntimeOption::NoInfiniteRecursionDetection = false;
527 bool RuntimeOption::AssertEmitted = true;
528 int64_t RuntimeOption::NoticeFrequency = 1;
529 int64_t RuntimeOption::WarningFrequency = 1;
530 int RuntimeOption::RaiseDebuggingFrequency = 1;
531 int64_t RuntimeOption::SerializationSizeLimit = StringData::MaxSize;
533 std::string RuntimeOption::AccessLogDefaultFormat = "%h %l %u %t \"%r\" %>s %b";
534 std::map<std::string, AccessLogFileData> RuntimeOption::AccessLogs;
536 std::string RuntimeOption::AdminLogFormat = "%h %t %s %U";
537 std::string RuntimeOption::AdminLogFile;
538 std::string RuntimeOption::AdminLogSymLink;
540 std::map<std::string, AccessLogFileData> RuntimeOption::RPCLogs;
542 std::string RuntimeOption::Host;
543 std::string RuntimeOption::DefaultServerNameSuffix;
544 std::string RuntimeOption::ServerType = "proxygen";
545 std::string RuntimeOption::ServerIP;
546 std::string RuntimeOption::ServerFileSocket;
547 int RuntimeOption::ServerPort = 80;
548 int RuntimeOption::ServerPortFd = -1;
549 int RuntimeOption::ServerBacklog = 128;
550 int RuntimeOption::ServerConnectionLimit = 0;
551 int RuntimeOption::ServerThreadCount = 50;
552 int RuntimeOption::ServerQueueCount = 50;
553 int RuntimeOption::ServerIOThreadCount = 1;
554 int RuntimeOption::ServerHighQueueingThreshold = 60;
555 bool RuntimeOption::ServerLegacyBehavior = true;
556 int RuntimeOption::ServerHugeThreadCount = 0;
557 int RuntimeOption::ServerHugeStackKb = 384;
558 uint32_t RuntimeOption::ServerLoopSampleRate = 0;
559 int RuntimeOption::ServerWarmupThrottleRequestCount = 0;
560 int RuntimeOption::ServerWarmupThrottleThreadCount = 0;
561 int RuntimeOption::ServerThreadDropCacheTimeoutSeconds = 0;
562 int RuntimeOption::ServerThreadJobLIFOSwitchThreshold = INT_MAX;
563 int RuntimeOption::ServerThreadJobMaxQueuingMilliSeconds = -1;
564 bool RuntimeOption::AlwaysDecodePostDataDefault = true;
565 bool RuntimeOption::ServerThreadDropStack = false;
566 bool RuntimeOption::ServerHttpSafeMode = false;
567 bool RuntimeOption::ServerStatCache = false;
568 bool RuntimeOption::ServerFixPathInfo = false;
569 bool RuntimeOption::ServerAddVaryEncoding = true;
570 bool RuntimeOption::ServerLogSettingsOnStartup = false;
571 bool RuntimeOption::ServerLogReorderProps = false;
572 bool RuntimeOption::ServerForkEnabled = true;
573 bool RuntimeOption::ServerForkLogging = false;
574 bool RuntimeOption::ServerWarmupConcurrently = false;
575 bool RuntimeOption::ServerDedupeWarmupRequests = false;
576 int RuntimeOption::ServerWarmupThreadCount = 1;
577 int RuntimeOption::ServerExtendedWarmupThreadCount = 1;
578 unsigned RuntimeOption::ServerExtendedWarmupRepeat = 1;
579 unsigned RuntimeOption::ServerExtendedWarmupDelaySeconds = 60;
580 std::vector<std::string> RuntimeOption::ServerWarmupRequests;
581 std::vector<std::string> RuntimeOption::ServerExtendedWarmupRequests;
582 std::string RuntimeOption::ServerCleanupRequest;
583 int RuntimeOption::ServerInternalWarmupThreads = 0;
584 boost::container::flat_set<std::string>
585 RuntimeOption::ServerHighPriorityEndPoints;
586 bool RuntimeOption::ServerExitOnBindFail;
587 int RuntimeOption::PageletServerThreadCount = 0;
588 int RuntimeOption::PageletServerHugeThreadCount = 0;
589 int RuntimeOption::PageletServerThreadDropCacheTimeoutSeconds = 0;
590 int RuntimeOption::PageletServerQueueLimit = 0;
591 bool RuntimeOption::PageletServerThreadDropStack = false;
592 int RuntimeOption::RequestTimeoutSeconds = 0;
593 int RuntimeOption::PspTimeoutSeconds = 0;
594 int RuntimeOption::PspCpuTimeoutSeconds = 0;
595 int64_t RuntimeOption::MaxRequestAgeFactor = 0;
596 int64_t RuntimeOption::RequestMemoryMaxBytes =
597 std::numeric_limits<int64_t>::max();
598 int64_t RuntimeOption::RequestHugeMaxBytes = 0;
599 int64_t RuntimeOption::ImageMemoryMaxBytes = 0;
600 int RuntimeOption::ServerGracefulShutdownWait = 0;
601 bool RuntimeOption::ServerHarshShutdown = true;
602 bool RuntimeOption::ServerEvilShutdown = true;
603 bool RuntimeOption::ServerKillOnTimeout = true;
604 bool RuntimeOption::Server503OnShutdownAbort = false;
605 int RuntimeOption::ServerPreShutdownWait = 0;
606 int RuntimeOption::ServerShutdownListenWait = 0;
607 int RuntimeOption::ServerShutdownEOMWait = 0;
608 int RuntimeOption::ServerPrepareToStopTimeout = 0;
609 int RuntimeOption::ServerPartialPostStatusCode = -1;
610 bool RuntimeOption::StopOldServer = false;
611 int RuntimeOption::OldServerWait = 30;
612 int RuntimeOption::CacheFreeFactor = 50;
613 int64_t RuntimeOption::ServerRSSNeededMb = 4096;
614 int64_t RuntimeOption::ServerCriticalFreeMb = 512;
615 std::vector<std::string> RuntimeOption::ServerNextProtocols;
616 bool RuntimeOption::ServerEnableH2C = false;
617 int RuntimeOption::BrotliCompressionEnabled = -1;
618 int RuntimeOption::BrotliChunkedCompressionEnabled = -1;
619 int RuntimeOption::BrotliCompressionMode = 0;
620 int RuntimeOption::BrotliCompressionQuality = 6;
621 int RuntimeOption::BrotliCompressionLgWindowSize = 20;
622 int RuntimeOption::ZstdCompressionEnabled = -1;
623 int RuntimeOption::ZstdCompressionLevel = 3;
624 int RuntimeOption::ZstdChecksumRate = 0;
625 int RuntimeOption::GzipCompressionLevel = 3;
626 int RuntimeOption::GzipMaxCompressionLevel = 9;
627 bool RuntimeOption::EnableKeepAlive = true;
628 bool RuntimeOption::ExposeHPHP = true;
629 bool RuntimeOption::ExposeXFBServer = false;
630 bool RuntimeOption::ExposeXFBDebug = false;
631 std::string RuntimeOption::XFBDebugSSLKey;
632 int RuntimeOption::ConnectionTimeoutSeconds = -1;
633 bool RuntimeOption::EnableOutputBuffering = false;
634 std::string RuntimeOption::OutputHandler;
635 bool RuntimeOption::ImplicitFlush = false;
636 bool RuntimeOption::EnableEarlyFlush = true;
637 bool RuntimeOption::ForceChunkedEncoding = false;
638 int64_t RuntimeOption::MaxPostSize = 100;
639 int64_t RuntimeOption::LowestMaxPostSize = LLONG_MAX;
640 bool RuntimeOption::AlwaysPopulateRawPostData = false;
641 int64_t RuntimeOption::UploadMaxFileSize = 100;
642 std::string RuntimeOption::UploadTmpDir = "/tmp";
643 bool RuntimeOption::EnableFileUploads = true;
644 bool RuntimeOption::EnableUploadProgress = false;
645 int64_t RuntimeOption::MaxFileUploads = 20;
646 int RuntimeOption::Rfc1867Freq = 256 * 1024;
647 std::string RuntimeOption::Rfc1867Prefix = "vupload_";
648 std::string RuntimeOption::Rfc1867Name = "video_ptoken";
649 bool RuntimeOption::ExpiresActive = true;
650 int RuntimeOption::ExpiresDefault = 2592000;
651 std::string RuntimeOption::DefaultCharsetName = "";
652 bool RuntimeOption::ForceServerNameToHeader = false;
653 bool RuntimeOption::PathDebug = false;
655 int64_t RuntimeOption::RequestBodyReadLimit = -1;
657 bool RuntimeOption::EnableSSL = false;
658 int RuntimeOption::SSLPort = 443;
659 int RuntimeOption::SSLPortFd = -1;
660 std::string RuntimeOption::SSLCertificateFile;
661 std::string RuntimeOption::SSLCertificateKeyFile;
662 std::string RuntimeOption::SSLCertificateDir;
663 std::string RuntimeOption::SSLTicketSeedFile;
664 bool RuntimeOption::TLSDisableTLS1_2 = false;
665 std::string RuntimeOption::TLSClientCipherSpec;
666 bool RuntimeOption::EnableSSLWithPlainText = false;
667 int RuntimeOption::SSLClientAuthLevel = 0;
668 std::string RuntimeOption::SSLClientCAFile = "";
670 std::string RuntimeOption::ClientAuthAclIdentity;
671 std::string RuntimeOption::ClientAuthAclAction;
672 bool RuntimeOption::ClientAuthFailClose = false;
673 uint32_t RuntimeOption::SSLClientAuthLoggingSampleRatio = 0;
674 uint32_t RuntimeOption::ClientAuthSuccessLogSampleRatio = 0;
675 uint32_t RuntimeOption::ClientAuthFailureLogSampleRatio = 0;
676 uint32_t RuntimeOption::ClientAuthLogSampleBase = 100;
678 std::vector<std::shared_ptr<VirtualHost>> RuntimeOption::VirtualHosts;
679 std::shared_ptr<IpBlockMap> RuntimeOption::IpBlocks;
680 std::vector<std::shared_ptr<SatelliteServerInfo>>
681 RuntimeOption::SatelliteServerInfos;
683 bool RuntimeOption::AllowRunAsRoot = false; // Allow running hhvm as root.
685 int RuntimeOption::XboxServerThreadCount = 10;
686 int RuntimeOption::XboxServerMaxQueueLength = INT_MAX;
687 int RuntimeOption::XboxServerPort = 0;
688 int RuntimeOption::XboxDefaultLocalTimeoutMilliSeconds = 500;
689 int RuntimeOption::XboxDefaultRemoteTimeoutSeconds = 5;
690 int RuntimeOption::XboxServerInfoMaxRequest = 500;
691 int RuntimeOption::XboxServerInfoDuration = 120;
692 std::string RuntimeOption::XboxServerInfoReqInitFunc;
693 std::string RuntimeOption::XboxServerInfoReqInitDoc;
694 bool RuntimeOption::XboxServerInfoAlwaysReset = false;
695 bool RuntimeOption::XboxServerLogInfo = false;
696 std::string RuntimeOption::XboxProcessMessageFunc = "xbox_process_message";
697 std::string RuntimeOption::XboxPassword;
698 std::set<std::string> RuntimeOption::XboxPasswords;
700 std::string RuntimeOption::SourceRoot = Process::GetCurrentDirectory() + '/';
701 std::vector<std::string> RuntimeOption::IncludeSearchPaths;
702 std::map<std::string, std::string> RuntimeOption::IncludeRoots;
703 std::map<std::string, std::string> RuntimeOption::AutoloadRoots;
704 bool RuntimeOption::AutoloadEnabled;
705 std::string RuntimeOption::AutoloadDBPath;
706 std::string RuntimeOption::FileCache;
707 std::string RuntimeOption::DefaultDocument;
708 std::string RuntimeOption::GlobalDocument;
709 std::string RuntimeOption::ErrorDocument404;
710 bool RuntimeOption::ForbiddenAs404 = false;
711 std::string RuntimeOption::ErrorDocument500;
712 std::string RuntimeOption::FatalErrorMessage;
713 std::string RuntimeOption::FontPath;
714 bool RuntimeOption::EnableStaticContentFromDisk = true;
715 bool RuntimeOption::EnableOnDemandUncompress = true;
716 bool RuntimeOption::EnableStaticContentMMap = true;
718 bool RuntimeOption::Utf8izeReplace = true;
720 std::string RuntimeOption::RequestInitFunction;
721 std::string RuntimeOption::RequestInitDocument;
722 std::string RuntimeOption::AutoPrependFile;
723 std::string RuntimeOption::AutoAppendFile;
725 bool RuntimeOption::SafeFileAccess = false;
726 std::vector<std::string> RuntimeOption::AllowedDirectories;
727 std::set<std::string> RuntimeOption::AllowedFiles;
728 hphp_string_imap<std::string> RuntimeOption::StaticFileExtensions;
729 hphp_string_imap<std::string> RuntimeOption::PhpFileExtensions;
730 std::set<std::string> RuntimeOption::ForbiddenFileExtensions;
731 std::vector<std::shared_ptr<FilesMatch>> RuntimeOption::FilesMatches;
733 bool RuntimeOption::WhitelistExec = false;
734 bool RuntimeOption::WhitelistExecWarningOnly = false;
735 std::vector<std::string> RuntimeOption::AllowedExecCmds;
737 bool RuntimeOption::UnserializationWhitelistCheck = false;
738 bool RuntimeOption::UnserializationWhitelistCheckWarningOnly = true;
739 int64_t RuntimeOption::UnserializationBigMapThreshold = 1 << 16;
741 std::string RuntimeOption::TakeoverFilename;
742 std::string RuntimeOption::AdminServerIP;
743 int RuntimeOption::AdminServerPort = 0;
744 int RuntimeOption::AdminThreadCount = 1;
745 bool RuntimeOption::AdminServerEnableSSLWithPlainText = false;
746 bool RuntimeOption::AdminServerStatsNeedPassword = true;
747 std::string RuntimeOption::AdminPassword;
748 std::set<std::string> RuntimeOption::AdminPasswords;
749 std::set<std::string> RuntimeOption::HashedAdminPasswords;
751 std::string RuntimeOption::ProxyOriginRaw;
752 int RuntimeOption::ProxyPercentageRaw = 0;
753 int RuntimeOption::ProxyRetry = 3;
754 bool RuntimeOption::UseServeURLs;
755 std::set<std::string> RuntimeOption::ServeURLs;
756 bool RuntimeOption::UseProxyURLs;
757 std::set<std::string> RuntimeOption::ProxyURLs;
758 std::vector<std::string> RuntimeOption::ProxyPatterns;
759 bool RuntimeOption::AlwaysUseRelativePath = false;
761 int RuntimeOption::HttpDefaultTimeout = 30;
762 int RuntimeOption::HttpSlowQueryThreshold = 5000; // ms
764 bool RuntimeOption::NativeStackTrace = false;
765 bool RuntimeOption::ServerErrorMessage = false;
766 bool RuntimeOption::RecordInput = false;
767 bool RuntimeOption::ClearInputOnSuccess = true;
768 std::string RuntimeOption::ProfilerOutputDir = "/tmp";
769 std::string RuntimeOption::CoreDumpEmail;
770 bool RuntimeOption::CoreDumpReport = true;
771 std::string RuntimeOption::CoreDumpReportDirectory =
772 #if defined(HPHP_OSS)
773 "/tmp";
774 #else
775 "/var/tmp/cores";
776 #endif
777 std::string RuntimeOption::StackTraceFilename;
778 int RuntimeOption::StackTraceTimeout = 0; // seconds; 0 means unlimited
779 std::string RuntimeOption::RemoteTraceOutputDir = "/tmp";
780 std::set<std::string, stdltistr> RuntimeOption::TraceFunctions;
781 uint32_t RuntimeOption::TraceFuncId = InvalidFuncId;
783 bool RuntimeOption::EnableStats = false;
784 bool RuntimeOption::EnableAPCStats = false;
785 bool RuntimeOption::EnableWebStats = false;
786 bool RuntimeOption::EnableMemoryStats = false;
787 bool RuntimeOption::EnableSQLStats = false;
788 bool RuntimeOption::EnableSQLTableStats = false;
789 bool RuntimeOption::EnableNetworkIOStatus = false;
790 std::string RuntimeOption::StatsXSL;
791 std::string RuntimeOption::StatsXSLProxy;
792 uint32_t RuntimeOption::StatsSlotDuration = 10 * 60; // 10 minutes
793 uint32_t RuntimeOption::StatsMaxSlot = 12 * 6; // 12 hours
795 int64_t RuntimeOption::MaxSQLRowCount = 0;
796 int64_t RuntimeOption::SocketDefaultTimeout = 60;
797 bool RuntimeOption::LockCodeMemory = false;
798 int RuntimeOption::MaxArrayChain = INT_MAX;
799 bool RuntimeOption::WarnOnCollectionToArray = false;
800 bool RuntimeOption::UseDirectCopy = false;
802 #if FOLLY_SANITIZE
803 bool RuntimeOption::DisableSmallAllocator = true;
804 #else
805 bool RuntimeOption::DisableSmallAllocator = false;
806 #endif
808 std::map<std::string, std::string> RuntimeOption::ServerVariables;
809 std::map<std::string, std::string> RuntimeOption::EnvVariables;
811 std::string RuntimeOption::LightProcessFilePrefix = "./lightprocess";
812 int RuntimeOption::LightProcessCount = 0;
814 int64_t RuntimeOption::HeapSizeMB = 4096; // 4gb
815 int64_t RuntimeOption::HeapResetCountBase = 1;
816 int64_t RuntimeOption::HeapResetCountMultiple = 2;
817 int64_t RuntimeOption::HeapLowWaterMark = 16;
818 int64_t RuntimeOption::HeapHighWaterMark = 1024;
819 uint64_t RuntimeOption::DisableCallUserFunc = 0;
820 uint64_t RuntimeOption::DisableCallUserFuncArray = 0;
821 uint64_t RuntimeOption::DisableAssert = 0;
822 uint64_t RuntimeOption::DisableConstant = 0;
823 bool RuntimeOption::DisableNontoplevelDeclarations = false;
824 bool RuntimeOption::DisableStaticClosures = false;
825 bool RuntimeOption::EnableClassLevelWhereClauses = false;
826 bool RuntimeOption::EnableFirstClassFunctionPointers = false;
828 #ifdef HHVM_DYNAMIC_EXTENSION_DIR
829 std::string RuntimeOption::ExtensionDir = HHVM_DYNAMIC_EXTENSION_DIR;
830 #else
831 std::string RuntimeOption::ExtensionDir = "";
832 #endif
834 std::vector<std::string> RuntimeOption::Extensions;
835 std::vector<std::string> RuntimeOption::DynamicExtensions;
836 std::string RuntimeOption::DynamicExtensionPath = ".";
837 int RuntimeOption::CheckCLIClientCommands = 0;
839 int RuntimeOption::CheckIntOverflow = 0;
840 HackStrictOption
841 RuntimeOption::StrictArrayFillKeys = HackStrictOption::OFF;
843 // defaults set when the INI option is bound - values below are irrelevant.
844 bool RuntimeOption::LookForTypechecker = false;
845 bool RuntimeOption::AutoTypecheck = false;
847 bool RuntimeOption::PHP7_EngineExceptions = false;
848 bool RuntimeOption::PHP7_NoHexNumerics = false;
849 bool RuntimeOption::PHP7_Builtins = false;
850 bool RuntimeOption::PHP7_Substr = false;
851 bool RuntimeOption::PHP7_DisallowUnsafeCurlUploads = false;
853 int RuntimeOption::GetScannerType() {
854 int type = 0;
855 if (EnableShortTags) type |= Scanner::AllowShortTags;
856 return type;
859 const std::string& RuntimeOption::GetServerPrimaryIPv4() {
860 static std::string serverPrimaryIPv4 = GetPrimaryIPv4();
861 return serverPrimaryIPv4;
864 const std::string& RuntimeOption::GetServerPrimaryIPv6() {
865 static std::string serverPrimaryIPv6 = GetPrimaryIPv6();
866 return serverPrimaryIPv6;
869 static inline std::string regionSelectorDefault() {
870 return "tracelet";
873 static inline bool pgoDefault() {
874 #ifdef HHVM_NO_DEFAULT_PGO
875 return false;
876 #else
877 return true;
878 #endif
881 static inline bool eagerGcDefault() {
882 #ifdef HHVM_EAGER_GC
883 return true;
884 #else
885 return false;
886 #endif
889 static inline std::string hackCompilerArgsDefault() {
890 return "--daemon --dump-symbol-refs";
893 static inline std::string hackCompilerCommandDefault() {
894 #ifdef FACEBOOK
895 return "";
896 #else
897 std::string hackc = folly::sformat(
898 "{}/hh_single_compile",
899 current_executable_directory()
901 if (::access(hackc.data(), X_OK) != 0) {
902 #ifndef HACKC_FALLBACK_PATH
903 return "";
904 #else
905 hackc = HACKC_FALLBACK_PATH;
906 if (::access(hackc.data(), X_OK) != 0) {
907 return "";
909 #endif
912 return folly::sformat(
913 "{} {}",
914 hackc,
915 hackCompilerArgsDefault()
917 #endif
920 static inline bool enableGcDefault() {
921 return RuntimeOption::EvalEagerGC || one_bit_refcount;
924 static inline uint64_t pgoThresholdDefault() {
925 return debug ? 2 : 2000;
928 static inline bool alignMacroFusionPairs() {
929 switch (getProcessorFamily()) {
930 case ProcessorFamily::Intel_SandyBridge:
931 case ProcessorFamily::Intel_IvyBridge:
932 case ProcessorFamily::Intel_Haswell:
933 case ProcessorFamily::Intel_Broadwell:
934 case ProcessorFamily::Intel_Skylake:
935 return true;
936 case ProcessorFamily::Unknown:
937 return false;
939 return false;
942 static inline bool armLseDefault() {
943 #if defined (__linux__) && defined (__aarch64__) && defined (HWCAP_ATOMICS)
944 return (getauxval(AT_HWCAP) & HWCAP_ATOMICS) != 0;
945 #else
946 return false;
947 #endif
950 static inline bool evalJitDefault() {
951 #ifdef _MSC_VER
952 return false;
953 #else
954 return true;
955 #endif
958 static inline bool reuseTCDefault() {
959 return hhvm_reuse_tc && !RuntimeOption::RepoAuthoritative;
962 static inline bool useFileBackedArenaDefault() {
963 return RuntimeOption::RepoAuthoritative &&
964 RuntimeOption::ServerExecutionMode();
967 static inline bool hugePagesSoundNice() {
968 return RuntimeOption::ServerExecutionMode();
971 static inline uint32_t hotTextHugePagesDefault() {
972 if (!hugePagesSoundNice()) return 0;
973 return arch() == Arch::ARM ? 12 : 8;
976 static inline std::string reorderPropsDefault() {
977 if (isJitDeserializing()) {
978 return "countedness-hotness";
980 return debug ? "alphabetical" : "countedness";
983 static inline uint32_t profileRequestsDefault() {
984 return debug ? std::numeric_limits<uint32_t>::max() : 2500;
987 static inline uint32_t profileBCSizeDefault() {
988 return debug ? std::numeric_limits<uint32_t>::max()
989 : RuntimeOption::EvalJitConcurrently ? 3750000
990 : 4300000;
993 static inline uint32_t resetProfCountersDefault() {
994 return RuntimeOption::EvalJitPGORacyProfiling
995 ? std::numeric_limits<uint32_t>::max()
996 : RuntimeOption::EvalJitConcurrently ? 250 : 1000;
999 static inline int retranslateAllRequestDefault() {
1000 return RuntimeOption::ServerExecutionMode() ? 1000000 : 0;
1003 static inline int retranslateAllSecondsDefault() {
1004 return RuntimeOption::ServerExecutionMode() ? 180 : 0;
1007 static inline bool pgoLayoutSplitHotColdDefault() {
1008 return arch() != Arch::ARM;
1011 static inline bool layoutPrologueSplitHotColdDefault() {
1012 return arch() != Arch::ARM;
1015 uint64_t ahotDefault() {
1016 return RuntimeOption::RepoAuthoritative ? 4 << 20 : 0;
1019 folly::Optional<folly::fs::path> RuntimeOption::GetHomePath(
1020 const folly::StringPiece user) {
1022 auto homePath = folly::fs::path{RuntimeOption::SandboxHome}
1023 / folly::fs::path{user};
1024 if (folly::fs::is_directory(homePath)) {
1025 return {std::move(homePath)};
1028 if (!RuntimeOption::SandboxFallback.empty()) {
1029 homePath = folly::fs::path{RuntimeOption::SandboxFallback}
1030 / folly::fs::path{user};
1031 if (folly::fs::is_directory(homePath)) {
1032 return {std::move(homePath)};
1036 return {};
1039 std::string RuntimeOption::GetDefaultUser() {
1040 if (SandboxDefaultUserFile.empty()) return {};
1042 folly::fs::path file{SandboxDefaultUserFile};
1043 if (!folly::fs::is_regular_file(file)) return {};
1045 std::string user;
1046 if (!folly::readFile(file.c_str(), user) || user.empty()) return {};
1048 return user;
1051 bool RuntimeOption::ReadPerUserSettings(const folly::fs::path& confFileName,
1052 IniSettingMap& ini, Hdf& config) {
1053 try {
1054 Config::ParseConfigFile(confFileName.native(), ini, config, false);
1055 return true;
1056 } catch (HdfException& e) {
1057 Logger::Error("%s ignored: %s", confFileName.native().c_str(),
1058 e.getMessage().c_str());
1059 return false;
1063 std::string RuntimeOption::getTraceOutputFile() {
1064 return folly::sformat("{}/hphp.{}.log",
1065 RuntimeOption::RemoteTraceOutputDir, (int64_t)getpid());
1068 const uint64_t kEvalVMStackElmsDefault =
1069 #if defined(VALGRIND) && !FOLLY_SANITIZE
1070 0x800
1071 #else
1072 0x4000
1073 #endif
1076 constexpr uint32_t kEvalVMInitialGlobalTableSizeDefault = 512;
1077 constexpr uint64_t kJitRelocationSizeDefault = 1 << 20;
1079 static const bool kJitTimerDefault =
1080 #ifdef ENABLE_JIT_TIMER_DEFAULT
1081 true
1082 #else
1083 false
1084 #endif
1087 using std::string;
1088 #define F(type, name, def) \
1089 type RuntimeOption::Eval ## name = type(def);
1090 EVALFLAGS();
1091 #undef F
1092 hphp_string_imap<TypedValue> RuntimeOption::ConstantFunctions;
1094 bool RuntimeOption::RecordCodeCoverage = false;
1095 std::string RuntimeOption::CodeCoverageOutputFile;
1097 std::string RuntimeOption::RepoLocalMode;
1098 std::string RuntimeOption::RepoLocalPath;
1099 std::string RuntimeOption::RepoCentralPath;
1100 int32_t RuntimeOption::RepoCentralFileMode;
1101 std::string RuntimeOption::RepoCentralFileUser;
1102 std::string RuntimeOption::RepoCentralFileGroup;
1103 std::string RuntimeOption::RepoEvalMode;
1104 std::string RuntimeOption::RepoJournal = "delete";
1105 bool RuntimeOption::RepoAllowFallbackPath = true;
1106 bool RuntimeOption::RepoCommit = true;
1107 bool RuntimeOption::RepoDebugInfo = true;
1108 bool RuntimeOption::RepoLitstrLazyLoad = true;
1109 // Missing: RuntimeOption::RepoAuthoritative's physical location is
1110 // perf-sensitive.
1111 bool RuntimeOption::RepoLocalReadaheadConcurrent = false;
1112 int64_t RuntimeOption::RepoLocalReadaheadRate = 0;
1113 uint32_t RuntimeOption::RepoBusyTimeoutMS = 15000;
1115 bool RuntimeOption::HHProfEnabled = false;
1116 bool RuntimeOption::HHProfActive = false;
1117 bool RuntimeOption::HHProfAccum = false;
1118 bool RuntimeOption::HHProfRequest = false;
1120 bool RuntimeOption::SandboxMode = false;
1121 std::string RuntimeOption::SandboxPattern;
1122 std::string RuntimeOption::SandboxHome;
1123 std::string RuntimeOption::SandboxFallback;
1124 std::string RuntimeOption::SandboxConfFile;
1125 std::map<std::string, std::string> RuntimeOption::SandboxServerVariables;
1126 bool RuntimeOption::SandboxFromCommonRoot = false;
1127 std::string RuntimeOption::SandboxDirectoriesRoot;
1128 std::string RuntimeOption::SandboxLogsRoot;
1129 std::string RuntimeOption::SandboxDefaultUserFile;
1130 std::string RuntimeOption::SandboxHostAlias;
1132 bool RuntimeOption::EnableHphpdDebugger = false;
1133 bool RuntimeOption::EnableVSDebugger = false;
1134 int RuntimeOption::VSDebuggerListenPort = -1;
1135 std::string RuntimeOption::VSDebuggerDomainSocketPath;
1136 bool RuntimeOption::VSDebuggerNoWait = false;
1137 bool RuntimeOption::EnableDebuggerColor = true;
1138 bool RuntimeOption::EnableDebuggerPrompt = true;
1139 bool RuntimeOption::EnableDebuggerServer = false;
1140 bool RuntimeOption::EnableDebuggerUsageLog = false;
1141 bool RuntimeOption::DebuggerDisableIPv6 = false;
1142 std::string RuntimeOption::DebuggerServerIP;
1143 int RuntimeOption::DebuggerServerPort = 8089;
1144 int RuntimeOption::DebuggerDefaultRpcPort = 8083;
1145 std::string RuntimeOption::DebuggerDefaultRpcAuth;
1146 std::string RuntimeOption::DebuggerRpcHostDomain;
1147 int RuntimeOption::DebuggerDefaultRpcTimeout = 30;
1148 std::string RuntimeOption::DebuggerDefaultSandboxPath;
1149 std::string RuntimeOption::DebuggerStartupDocument;
1150 int RuntimeOption::DebuggerSignalTimeout = 1;
1151 std::string RuntimeOption::DebuggerAuthTokenScriptBin;
1152 std::string RuntimeOption::DebuggerSessionAuthScriptBin;
1154 std::string RuntimeOption::SendmailPath = "sendmail -t -i";
1155 std::string RuntimeOption::MailForceExtraParameters;
1157 int64_t RuntimeOption::PregBacktraceLimit = 1000000;
1158 int64_t RuntimeOption::PregRecursionLimit = 100000;
1159 bool RuntimeOption::EnablePregErrorLog = true;
1161 bool RuntimeOption::SimpleXMLEmptyNamespaceMatchesAll = false;
1163 bool RuntimeOption::AllowDuplicateCookies = true;
1165 bool RuntimeOption::EnableHotProfiler = true;
1166 int RuntimeOption::ProfilerTraceBuffer = 2000000;
1167 double RuntimeOption::ProfilerTraceExpansion = 1.2;
1168 int RuntimeOption::ProfilerMaxTraceBuffer = 0;
1170 #ifdef FACEBOOK
1171 bool RuntimeOption::EnableFb303Server = false;
1172 int RuntimeOption::Fb303ServerPort = 0;
1173 int RuntimeOption::Fb303ServerThreadStackSizeMb = 8;
1174 int RuntimeOption::Fb303ServerWorkerThreads = 1;
1175 int RuntimeOption::Fb303ServerPoolThreads = 1;
1176 #endif
1178 double RuntimeOption::XenonPeriodSeconds = 0.0;
1179 uint32_t RuntimeOption::XenonRequestFreq = 1;
1180 bool RuntimeOption::XenonForceAlwaysOn = false;
1182 bool RuntimeOption::StrobelightEnabled = false;
1184 bool RuntimeOption::TrackPerUnitMemory = false;
1186 bool RuntimeOption::SetProfileNullThisObject = true;
1188 std::map<std::string, std::string> RuntimeOption::CustomSettings;
1190 #ifdef NDEBUG
1191 #ifdef ALWAYS_ASSERT
1192 const StaticString s_hhvm_build_type("Release with asserts");
1193 #else
1194 const StaticString s_hhvm_build_type("Release");
1195 #endif
1196 #else
1197 const StaticString s_hhvm_build_type("Debug");
1198 #endif
1200 ///////////////////////////////////////////////////////////////////////////////
1202 static void setResourceLimit(int resource, const IniSetting::Map& ini,
1203 const Hdf& rlimit, const char* nodeName) {
1204 if (!Config::GetString(ini, rlimit, nodeName).empty()) {
1205 struct rlimit rl;
1206 getrlimit(resource, &rl);
1207 rl.rlim_cur = Config::GetInt64(ini, rlimit, nodeName);
1208 if (rl.rlim_max < rl.rlim_cur) {
1209 rl.rlim_max = rl.rlim_cur;
1211 int ret = setrlimit(resource, &rl);
1212 if (ret) {
1213 Logger::Error("Unable to set %s to %" PRId64 ": %s (%d)",
1214 nodeName, (int64_t)rl.rlim_cur,
1215 folly::errnoStr(errno).c_str(), errno);
1220 static void normalizePath(std::string &path) {
1221 if (!path.empty()) {
1222 if (path[path.length() - 1] == '/') {
1223 path = path.substr(0, path.length() - 1);
1225 if (path[0] != '/') {
1226 path = std::string("/") + path;
1231 static bool matchShard(
1232 const std::string& hostname,
1233 const IniSetting::Map& ini, Hdf hdfPattern,
1234 std::vector<std::string>& messages
1236 if (!hdfPattern.exists("Shard")) return true;
1237 auto const shard = Config::GetInt64(ini, hdfPattern, "Shard", -1, false);
1239 auto const nshards =
1240 Config::GetInt64(ini, hdfPattern, "ShardCount", 100, false);
1242 if (shard < 0 || shard >= nshards) {
1243 messages.push_back(folly::sformat("Invalid value for Shard: {}", shard));
1244 return true;
1247 auto input = hostname;
1248 if (hdfPattern.exists("ShardSalt")) {
1249 input += Config::GetString(ini, hdfPattern, "ShardSalt", "", false);
1252 auto const md5 = Md5Digest(input.data(), input.size());
1253 uint32_t seed{0};
1254 memcpy(&seed, &md5.digest[0], 4);
1256 // This shift is to match the behavior of sharding in chef which appears to
1257 // have an off-by-one bug:
1258 // seed = Digest::MD5.hexdigest(seed_input)[0...7].to_i(16)
1259 seed = ntohl(seed) >> 4;
1261 messages.push_back(folly::sformat(
1262 "Checking Shard = {}; Input = {}; Seed = {}; ShardCount = {}; Value = {}",
1263 shard, input, seed, nshards, seed % nshards
1266 return seed % nshards <= shard;
1269 // A machine can belong to a tier, which can overwrite
1270 // various settings, even if they are set in the same
1271 // hdf file. However, CLI overrides still win the day over
1272 // everything.
1273 static std::vector<std::string> getTierOverwrites(IniSetting::Map& ini,
1274 Hdf& config) {
1276 // Machine metrics
1277 string hostname, tier, task, cpu, tiers, tags;
1279 hostname = Config::GetString(ini, config, "Machine.name");
1280 if (hostname.empty()) {
1281 hostname = Process::GetHostName();
1284 tier = Config::GetString(ini, config, "Machine.tier");
1286 task = Config::GetString(ini, config, "Machine.task");
1288 cpu = Config::GetString(ini, config, "Machine.cpu");
1289 if (cpu.empty()) {
1290 cpu = Process::GetCPUModel();
1293 tiers = Config::GetString(ini, config, "Machine.tiers");
1294 if (!tiers.empty()) {
1295 if (!folly::readFile(tiers.c_str(), tiers)) {
1296 tiers.clear();
1300 tags = Config::GetString(ini, config, "Machine.tags");
1301 if (!tags.empty()) {
1302 if (!folly::readFile(tags.c_str(), tags)) {
1303 tags.clear();
1308 auto const checkPatterns = [&] (Hdf hdf) {
1309 // Check the patterns using "&" rather than "&&" so they all get
1310 // evaluated; otherwise with multiple patterns, if an earlier
1311 // one fails to match, the later one is reported as unused.
1312 return
1313 Config::matchHdfPattern(hostname, ini, hdf, "machine") &
1314 Config::matchHdfPattern(tier, ini, hdf, "tier") &
1315 Config::matchHdfPattern(task, ini, hdf, "task") &
1316 Config::matchHdfPattern(tiers, ini, hdf, "tiers", "m") &
1317 Config::matchHdfPattern(tags, ini, hdf, "tags", "m") &
1318 Config::matchHdfPattern(cpu, ini, hdf, "cpu");
1321 std::vector<std::string> messages;
1322 // Tier overwrites
1324 for (Hdf hdf = config["Tiers"].firstChild(); hdf.exists();
1325 hdf = hdf.next()) {
1326 if (messages.empty()) {
1327 messages.emplace_back(folly::sformat(
1328 "Matching tiers using: "
1329 "machine='{}', tier='{}', task='{}', "
1330 "cpu='{}', tiers='{}', tags='{}'",
1331 hostname, tier, task, cpu, tiers, tags));
1333 // Check the patterns using "&" rather than "&&" so they all get
1334 // evaluated; otherwise with multiple patterns, if an earlier
1335 // one fails to match, the later one is reported as unused.
1336 if (checkPatterns(hdf) &
1337 (!hdf.exists("exclude") || !checkPatterns(hdf["exclude"])) &
1338 matchShard(hostname, ini, hdf, messages)) {
1339 messages.emplace_back(folly::sformat(
1340 "Matched tier: {}", hdf.getName()));
1341 if (hdf.exists("clear")) {
1342 std::vector<std::string> list;
1343 hdf["clear"].configGet(list);
1344 for (auto const& s : list) {
1345 config.remove(s);
1348 config.copy(hdf["overwrite"]);
1349 // no break here, so we can continue to match more overwrites
1351 hdf["overwrite"].setVisited(); // avoid lint complaining
1352 if (hdf.exists("clear")) {
1353 // when the tier does not match, "clear" is not accessed
1354 // mark it visited, so the linter does not complain
1355 hdf["clear"].setVisited();
1359 return messages;
1362 void RuntimeOption::ReadSatelliteInfo(
1363 const IniSettingMap& ini,
1364 const Hdf& hdf,
1365 std::vector<std::shared_ptr<SatelliteServerInfo>>& infos,
1366 std::string& xboxPassword,
1367 std::set<std::string>& xboxPasswords) {
1368 auto ss_callback = [&] (const IniSettingMap &ini_ss, const Hdf &hdf_ss,
1369 const std::string &ini_ss_key) {
1370 auto satellite = std::make_shared<SatelliteServerInfo>(ini_ss, hdf_ss,
1371 ini_ss_key);
1372 infos.push_back(satellite);
1373 if (satellite->getType() == SatelliteServer::Type::KindOfRPCServer) {
1374 xboxPassword = satellite->getPassword();
1375 xboxPasswords = satellite->getPasswords();
1378 Config::Iterate(ss_callback, ini, hdf, "Satellites");
1381 extern void initialize_apc();
1382 void RuntimeOption::Load(
1383 IniSetting::Map& ini, Hdf& config,
1384 const std::vector<std::string>& iniClis /* = std::vector<std::string>() */,
1385 const std::vector<std::string>& hdfClis /* = std::vector<std::string>() */,
1386 std::vector<std::string>* messages /* = nullptr */,
1387 std::string cmd /* = "" */) {
1388 ARRPROV_USE_RUNTIME_LOCATION_FORCE();
1390 // Intialize the memory manager here because various settings and
1391 // initializations that we do here need it
1392 tl_heap.getCheck();
1394 // Get the ini (-d) and hdf (-v) strings, which may override some
1395 // of options that were set from config files. We also do these
1396 // now so we can override Tier.*.[machine | tier | cpu] on the
1397 // command line, along with any fields within a Tier (e.g.,
1398 // CoreFileSize)
1399 for (auto& istr : iniClis) {
1400 Config::ParseIniString(istr, ini);
1402 for (auto& hstr : hdfClis) {
1403 Config::ParseHdfString(hstr, config);
1406 // See if there are any Tier-based overrides
1407 auto m = getTierOverwrites(ini, config);
1408 if (messages) *messages = std::move(m);
1410 // RelativeConfigs can be set by commandline flags and tier overwrites, they
1411 // may also contain tier overwrites. They are, however, only included once, so
1412 // relative configs may not specify other relative configs which must to be
1413 // loaded. If RelativeConfigs is modified while loading configs an error is
1414 // raised, but we defer doing so until the logger is initialized below. If a
1415 // relative config cannot be found it is silently skipped (this is to allow
1416 // configs to be conditionally applied to scripts based on their location). By
1417 // reading the "hhvm.relative_configs" ini setting at runtime it is possible
1418 // to determine which configs were actually loaded.
1419 std::string relConfigsError;
1420 Config::Bind(s_RelativeConfigs, ini, config, "RelativeConfigs");
1421 if (!cmd.empty() && !s_RelativeConfigs.empty()) {
1422 String strcmd(cmd, CopyString);
1423 Process::InitProcessStatics();
1424 auto const currentDir = Process::CurrentWorkingDirectory.data();
1425 std::vector<std::string> newConfigs;
1426 auto const original = s_RelativeConfigs;
1427 for (auto& str : original) {
1428 if (str.empty()) continue;
1430 std::string fullpath;
1431 auto const found = FileUtil::runRelative(
1432 str, strcmd, currentDir,
1433 [&] (const String& f) {
1434 if (access(f.data(), R_OK) == 0) {
1435 fullpath = f.toCppString();
1436 FTRACE_MOD(Trace::watchman_autoload, 3, "Parsing {}\n", fullpath);
1437 Config::ParseConfigFile(fullpath, ini, config);
1438 return true;
1440 return false;
1443 if (found) newConfigs.emplace_back(std::move(fullpath));
1445 if (!newConfigs.empty()) {
1446 auto m2 = getTierOverwrites(ini, config);
1447 if (messages) *messages = std::move(m2);
1448 if (s_RelativeConfigs != original) {
1449 relConfigsError = folly::sformat(
1450 "RelativeConfigs node was modified while loading configs from [{}] "
1451 "to [{}]",
1452 folly::join(", ", original),
1453 folly::join(", ", s_RelativeConfigs)
1457 s_RelativeConfigs.swap(newConfigs);
1458 } else {
1459 s_RelativeConfigs.clear();
1462 // Then get the ini and hdf cli strings again, in case the tier overwrites
1463 // overrode any non-tier based command line option we set. The tier-based
1464 // command line overwrites will already have been set in the call above.
1465 // This extra call is for the other command line options that may have been
1466 // overridden by a tier, but shouldn't have been.
1467 for (auto& istr : iniClis) {
1468 Config::ParseIniString(istr, ini);
1470 for (auto& hstr : hdfClis) {
1471 Config::ParseHdfString(hstr, config);
1474 Config::Bind(PidFile, ini, config, "PidFile", "www.pid");
1475 Config::Bind(DeploymentId, ini, config, "DeploymentId");
1478 static std::string deploymentIdOverride;
1479 Config::Bind(deploymentIdOverride, ini, config, "DeploymentIdOverride");
1480 if (!deploymentIdOverride.empty()) {
1481 RuntimeOption::DeploymentId = deploymentIdOverride;
1486 // Config ID
1487 Config::Bind(ConfigId, ini, config, "ConfigId", 0);
1488 auto configIdCounter = ServiceData::createCounter("vm.config.id");
1489 configIdCounter->setValue(ConfigId);
1493 // Logging
1494 auto setLogLevel = [](const std::string& value) {
1495 // ini parsing treats "None" as ""
1496 if (value == "None" || value == "") {
1497 Logger::LogLevel = Logger::LogNone;
1498 } else if (value == "Error") {
1499 Logger::LogLevel = Logger::LogError;
1500 } else if (value == "Warning") {
1501 Logger::LogLevel = Logger::LogWarning;
1502 } else if (value == "Info") {
1503 Logger::LogLevel = Logger::LogInfo;
1504 } else if (value == "Verbose") {
1505 Logger::LogLevel = Logger::LogVerbose;
1506 } else {
1507 return false;
1509 return true;
1511 auto str = Config::GetString(ini, config, "Log.Level");
1512 if (!str.empty()) {
1513 setLogLevel(str);
1515 IniSetting::Bind(IniSetting::CORE, IniSetting::PHP_INI_SYSTEM,
1516 "hhvm.log.level", IniSetting::SetAndGet<std::string>(
1517 setLogLevel,
1518 []() {
1519 switch (Logger::LogLevel) {
1520 case Logger::LogNone:
1521 return "None";
1522 case Logger::LogError:
1523 return "Error";
1524 case Logger::LogWarning:
1525 return "Warning";
1526 case Logger::LogInfo:
1527 return "Info";
1528 case Logger::LogVerbose:
1529 return "Verbose";
1531 return "";
1535 Config::Bind(Logger::UseLogFile, ini, config, "Log.UseLogFile", true);
1536 Config::Bind(LogFile, ini, config, "Log.File");
1537 Config::Bind(LogFileSymLink, ini, config, "Log.SymLink");
1538 Config::Bind(LogFilePeriodMultiplier, ini,
1539 config, "Log.PeriodMultiplier", 0);
1540 if (Logger::UseLogFile && RuntimeOption::ServerExecutionMode()) {
1541 RuntimeOption::ErrorLogs[Logger::DEFAULT] =
1542 ErrorLogFileData(LogFile, LogFileSymLink, LogFilePeriodMultiplier);
1544 if (Config::GetBool(ini, config, "Log.AlwaysPrintStackTraces")) {
1545 Logger::SetTheLogger(Logger::DEFAULT, new ExtendedLogger());
1546 ExtendedLogger::EnabledByDefault = true;
1549 Config::Bind(Logger::LogHeader, ini, config, "Log.Header");
1550 Config::Bind(Logger::LogNativeStackTrace, ini, config,
1551 "Log.NativeStackTrace", true);
1552 Config::Bind(Logger::UseSyslog, ini, config, "Log.UseSyslog", false);
1553 Config::Bind(Logger::UseRequestLog, ini, config, "Log.UseRequestLog",
1554 false);
1555 Config::Bind(Logger::AlwaysEscapeLog, ini, config, "Log.AlwaysEscapeLog",
1556 true);
1557 Config::Bind(Logger::UseCronolog, ini, config, "Log.UseCronolog", false);
1558 Config::Bind(Logger::MaxMessagesPerRequest, ini,
1559 config, "Log.MaxMessagesPerRequest", -1);
1560 Config::Bind(LogFileFlusher::DropCacheChunkSize, ini,
1561 config, "Log.DropCacheChunkSize", 1 << 20);
1562 Config::Bind(RuntimeOption::LogHeaderMangle, ini, config,
1563 "Log.HeaderMangle", 0);
1564 Config::Bind(AlwaysLogUnhandledExceptions, ini,
1565 config, "Log.AlwaysLogUnhandledExceptions",
1566 true);
1567 Config::Bind(NoSilencer, ini, config, "Log.NoSilencer");
1568 Config::Bind(RuntimeErrorReportingLevel, ini,
1569 config, "Log.RuntimeErrorReportingLevel",
1570 static_cast<int>(ErrorMode::HPHP_ALL));
1571 Config::Bind(ForceErrorReportingLevel, ini,
1572 config, "Log.ForceErrorReportingLevel", 0);
1573 Config::Bind(AccessLogDefaultFormat, ini, config,
1574 "Log.AccessLogDefaultFormat", "%h %l %u %t \"%r\" %>s %b");
1576 auto parseLogs = [] (const Hdf &config, const IniSetting::Map& ini,
1577 const std::string &name,
1578 std::map<std::string, AccessLogFileData> &logs) {
1579 auto parse_logs_callback = [&] (const IniSetting::Map &ini_pl,
1580 const Hdf &hdf_pl,
1581 const std::string &ini_pl_key) {
1582 string logName = hdf_pl.exists() && !hdf_pl.isEmpty()
1583 ? hdf_pl.getName()
1584 : ini_pl_key;
1585 string fname = Config::GetString(ini_pl, hdf_pl, "File", "", false);
1586 if (!fname.empty()) {
1587 string symlink = Config::GetString(ini_pl, hdf_pl, "SymLink", "",
1588 false);
1589 string format = Config::GetString(ini_pl, hdf_pl, "Format",
1590 AccessLogDefaultFormat, false);
1591 auto periodMultiplier = Config::GetUInt16(ini_pl, hdf_pl,
1592 "PeriodMultiplier",
1593 0, false);
1594 logs[logName] = AccessLogFileData(fname, symlink,
1595 format, periodMultiplier);
1600 Config::Iterate(parse_logs_callback, ini, config, name);
1603 parseLogs(config, ini, "Log.Access", AccessLogs);
1604 RPCLogs = AccessLogs;
1605 parseLogs(config, ini, "Log.RPC", RPCLogs);
1607 Config::Bind(AdminLogFormat, ini, config, "Log.AdminLog.Format",
1608 "%h %t %s %U");
1609 Config::Bind(AdminLogFile, ini, config, "Log.AdminLog.File");
1610 Config::Bind(AdminLogSymLink, ini, config, "Log.AdminLog.SymLink");
1613 // Error Handling
1615 Config::Bind(ErrorUpgradeLevel, ini, config, "ErrorHandling.UpgradeLevel",
1617 Config::Bind(MaxSerializedStringSize, ini,
1618 config, "ErrorHandling.MaxSerializedStringSize",
1619 64 * 1024 * 1024);
1620 Config::Bind(CallUserHandlerOnFatals, ini,
1621 config, "ErrorHandling.CallUserHandlerOnFatals", false);
1622 Config::Bind(ThrowExceptionOnBadMethodCall, ini,
1623 config, "ErrorHandling.ThrowExceptionOnBadMethodCall", true);
1624 Config::Bind(LogNativeStackOnOOM, ini,
1625 config, "ErrorHandling.LogNativeStackOnOOM", false);
1626 Config::Bind(NoInfiniteRecursionDetection, ini,
1627 config, "ErrorHandling.NoInfiniteRecursionDetection");
1628 Config::Bind(NoticeFrequency, ini, config, "ErrorHandling.NoticeFrequency",
1630 Config::Bind(WarningFrequency, ini, config,
1631 "ErrorHandling.WarningFrequency", 1);
1634 // If we generated errors while loading RelativeConfigs report those now that
1635 // error reporting is initialized
1636 if (!relConfigsError.empty()) Logger::Error(relConfigsError);
1639 if (Config::GetInt64(ini, config, "ResourceLimit.CoreFileSizeOverride")) {
1640 setResourceLimit(RLIMIT_CORE, ini, config,
1641 "ResourceLimit.CoreFileSizeOverride");
1642 } else {
1643 setResourceLimit(RLIMIT_CORE, ini, config, "ResourceLimit.CoreFileSize");
1645 setResourceLimit(RLIMIT_NOFILE, ini, config, "ResourceLimit.MaxSocket");
1646 setResourceLimit(RLIMIT_DATA, ini, config, "ResourceLimit.RSS");
1647 // These don't have RuntimeOption::xxx bindings, but we still want to be
1648 // able to use ini_xxx functionality on them; so directly bind to a local
1649 // static via Config::Bind.
1650 static int64_t s_core_file_size_override, s_core_file_size, s_rss = 0;
1651 static int32_t s_max_socket = 0;
1652 Config::Bind(s_core_file_size_override, ini, config,
1653 "ResourceLimit.CoreFileSizeOverride", 0);
1654 Config::Bind(s_core_file_size, ini, config, "ResourceLimit.CoreFileSize",
1656 Config::Bind(s_max_socket, ini, config, "ResourceLimit.MaxSocket", 0);
1657 Config::Bind(s_rss, ini, config, "ResourceLimit.RSS", 0);
1659 Config::Bind(SocketDefaultTimeout, ini, config,
1660 "ResourceLimit.SocketDefaultTimeout", 60);
1661 Config::Bind(MaxSQLRowCount, ini, config, "ResourceLimit.MaxSQLRowCount",
1663 Config::Bind(SerializationSizeLimit, ini, config,
1664 "ResourceLimit.SerializationSizeLimit", StringData::MaxSize);
1665 Config::Bind(HeapSizeMB, ini, config, "ResourceLimit.HeapSizeMB",
1666 HeapSizeMB);
1667 Config::Bind(HeapResetCountBase, ini, config,
1668 "ResourceLimit.HeapResetCountBase", HeapResetCountBase);
1669 Config::Bind(HeapResetCountMultiple, ini, config,
1670 "ResourceLimit.HeapResetCountMultiple",
1671 HeapResetCountMultiple);
1672 Config::Bind(HeapLowWaterMark , ini, config,
1673 "ResourceLimit.HeapLowWaterMark", HeapLowWaterMark);
1674 Config::Bind(HeapHighWaterMark , ini, config,
1675 "ResourceLimit.HeapHighWaterMark",HeapHighWaterMark);
1678 // PHPisms
1679 Config::Bind(DisableCallUserFunc, ini, config,
1680 "Hack.Lang.Phpism.DisableCallUserFunc",
1681 DisableCallUserFunc);
1682 Config::Bind(DisableCallUserFuncArray, ini, config,
1683 "Hack.Lang.Phpism.DisableCallUserFuncArray",
1684 DisableCallUserFuncArray);
1685 Config::Bind(DisableAssert, ini, config,
1686 "Hack.Lang.Phpism.DisableAssert",
1687 DisableAssert);
1688 Config::Bind(DisableNontoplevelDeclarations, ini, config,
1689 "Hack.Lang.Phpism.DisableNontoplevelDeclarations",
1690 DisableNontoplevelDeclarations);
1691 Config::Bind(DisableStaticClosures, ini, config,
1692 "Hack.Lang.Phpism.DisableStaticClosures",
1693 DisableStaticClosures);
1694 Config::Bind(DisableConstant, ini, config,
1695 "Hack.Lang.Phpism.DisableConstant",
1696 DisableConstant);
1699 // Repo
1700 // Local Repo
1701 Config::Bind(RepoLocalMode, ini, config, "Repo.Local.Mode", RepoLocalMode);
1702 if (RepoLocalMode.empty()) {
1703 const char* HHVM_REPO_LOCAL_MODE = getenv("HHVM_REPO_LOCAL_MODE");
1704 if (HHVM_REPO_LOCAL_MODE != nullptr) {
1705 RepoLocalMode = HHVM_REPO_LOCAL_MODE;
1707 RepoLocalMode = "r-";
1709 if (RepoLocalMode.compare("rw")
1710 && RepoLocalMode.compare("r-")
1711 && RepoLocalMode.compare("--")) {
1712 Logger::Error("Bad config setting: Repo.Local.Mode=%s",
1713 RepoLocalMode.c_str());
1714 RepoLocalMode = "rw";
1716 // Repo.Local.Path
1717 Config::Bind(RepoLocalPath, ini, config, "Repo.Local.Path");
1718 if (RepoLocalPath.empty()) {
1719 const char* HHVM_REPO_LOCAL_PATH = getenv("HHVM_REPO_LOCAL_PATH");
1720 if (HHVM_REPO_LOCAL_PATH != nullptr) {
1721 RepoLocalPath = HHVM_REPO_LOCAL_PATH;
1725 // Central Repo
1726 Config::Bind(RepoCentralPath, ini, config, "Repo.Central.Path");
1727 Config::Bind(RepoCentralFileMode, ini, config, "Repo.Central.FileMode");
1728 Config::Bind(RepoCentralFileUser, ini, config, "Repo.Central.FileUser");
1729 Config::Bind(RepoCentralFileGroup, ini, config, "Repo.Central.FileGroup");
1731 Config::Bind(RepoAllowFallbackPath, ini, config, "Repo.AllowFallbackPath",
1732 RepoAllowFallbackPath);
1734 replacePlaceholders(RepoLocalPath);
1735 replacePlaceholders(RepoCentralPath);
1737 // Repo - Eval
1738 Config::Bind(RepoEvalMode, ini, config, "Repo.Eval.Mode");
1739 if (RepoEvalMode.empty()) {
1740 RepoEvalMode = "readonly";
1741 } else if (RepoEvalMode.compare("local")
1742 && RepoEvalMode.compare("central")
1743 && RepoEvalMode.compare("readonly")) {
1744 Logger::Error("Bad config setting: Repo.Eval.Mode=%s",
1745 RepoEvalMode.c_str());
1746 RepoEvalMode = "readonly";
1749 Config::Bind(RepoJournal, ini, config, "Repo.Journal", RepoJournal);
1750 Config::Bind(RepoCommit, ini, config, "Repo.Commit",
1751 RepoCommit);
1752 Config::Bind(RepoDebugInfo, ini, config, "Repo.DebugInfo", RepoDebugInfo);
1753 Config::Bind(RepoLitstrLazyLoad, ini, config, "Repo.LitstrLazyLoad",
1754 RepoLitstrLazyLoad);
1755 Config::Bind(RepoAuthoritative, ini, config, "Repo.Authoritative",
1756 RepoAuthoritative);
1757 Config::Bind(RepoLocalReadaheadRate, ini, config,
1758 "Repo.LocalReadaheadRate", 0);
1759 Config::Bind(RepoLocalReadaheadConcurrent, ini, config,
1760 "Repo.LocalReadaheadConcurrent", false);
1761 Config::Bind(RepoBusyTimeoutMS, ini, config,
1762 "Repo.BusyTimeoutMS", RepoBusyTimeoutMS);
1765 if (use_jemalloc) {
1766 // HHProf
1767 Config::Bind(HHProfEnabled, ini, config, "HHProf.Enabled", false);
1768 Config::Bind(HHProfActive, ini, config, "HHProf.Active", false);
1769 Config::Bind(HHProfAccum, ini, config, "HHProf.Accum", false);
1770 Config::Bind(HHProfRequest, ini, config, "HHProf.Request", false);
1773 // Eval
1774 Config::Bind(EnableHipHopSyntax, ini, config, "Eval.EnableHipHopSyntax",
1775 EnableHipHopSyntax);
1776 Config::Bind(EnableShortTags, ini, config, "Eval.EnableShortTags", true);
1777 Config::Bind(EnableXHP, ini, config, "Eval.EnableXHP", EnableXHP);
1778 Config::Bind(TimeoutsUseWallTime, ini, config, "Eval.TimeoutsUseWallTime",
1779 true);
1780 Config::Bind(CheckFlushOnUserClose, ini, config,
1781 "Eval.CheckFlushOnUserClose", true);
1782 Config::Bind(EvalInitialNamedEntityTableSize, ini, config,
1783 "Eval.InitialNamedEntityTableSize",
1784 EvalInitialNamedEntityTableSize);
1785 Config::Bind(EvalInitialStaticStringTableSize, ini, config,
1786 "Eval.InitialStaticStringTableSize",
1787 EvalInitialStaticStringTableSize);
1789 static std::string jitSerdesMode;
1790 Config::Bind(jitSerdesMode, ini, config, "Eval.JitSerdesMode", "Off");
1792 EvalJitSerdesMode = [&] {
1793 #define X(x) if (jitSerdesMode == #x) return JitSerdesMode::x
1794 X(Serialize);
1795 X(SerializeAndExit);
1796 X(Deserialize);
1797 X(DeserializeOrFail);
1798 X(DeserializeOrGenerate);
1799 X(DeserializeAndDelete);
1800 X(DeserializeAndExit);
1801 #undef X
1802 return JitSerdesMode::Off;
1803 }();
1804 Config::Bind(EvalJitSerdesFile, ini, config,
1805 "Eval.JitSerdesFile", EvalJitSerdesFile);
1806 // DumpPreciseProfileData defaults to true only when we can possibly write
1807 // profile data to disk. It can be set to false to avoid the performance
1808 // penalty of only running the interpreter during retranslateAll. We will
1809 // assume that DumpPreciseProfileData implies (JitSerdesMode::Serialize ||
1810 // JitSerdesMode::SerializeAndExit), to avoid checking too many flags in a
1811 // few places. The config file should never need to explicitly set
1812 // DumpPreciseProfileData to true.
1813 auto const couldDump = !EvalJitSerdesFile.empty() &&
1814 (isJitSerializing() ||
1815 (EvalJitSerdesMode == JitSerdesMode::DeserializeOrGenerate));
1816 Config::Bind(DumpPreciseProfData, ini, config,
1817 "Eval.DumpPreciseProfData", couldDump);
1818 Config::Bind(ProfDataTTLHours, ini, config,
1819 "Eval.ProfDataTTLHours", ProfDataTTLHours);
1820 Config::Bind(ProfDataTag, ini, config, "Eval.ProfDataTag", ProfDataTag);
1822 Config::Bind(CheckSymLink, ini, config, "Eval.CheckSymLink", true);
1823 Config::Bind(TrustAutoloaderPath, ini, config,
1824 "Eval.TrustAutoloaderPath", false);
1826 #define F(type, name, defaultVal) \
1827 Config::Bind(Eval ## name, ini, config, "Eval."#name, defaultVal);
1828 EVALFLAGS()
1829 #undef F
1831 if (EvalJitSerdesModeForceOff) EvalJitSerdesMode = JitSerdesMode::Off;
1832 if (!EvalEnableReusableTC) EvalReusableTCPadding = 0;
1833 if (numa_num_nodes <= 1) {
1834 EvalEnableNuma = false;
1837 Config::Bind(ServerForkEnabled, ini, config,
1838 "Server.Forking.Enabled", ServerForkEnabled);
1839 Config::Bind(ServerForkLogging, ini, config,
1840 "Server.Forking.LogForkAttempts", ServerForkLogging);
1841 if (!ServerForkEnabled && ServerExecutionMode()) {
1842 // Only use hugetlb pages when we don't fork().
1843 low_2m_pages(EvalMaxLowMemHugePages);
1844 high_2m_pages(EvalMaxHighArenaHugePages);
1847 replacePlaceholders(EvalHackCompilerExtractPath);
1848 replacePlaceholders(EvalHackCompilerFallbackPath);
1849 replacePlaceholders(EvalEmbeddedDataExtractPath);
1850 replacePlaceholders(EvalEmbeddedDataFallbackPath);
1852 if (!jit::mcgen::retranslateAllEnabled()) {
1853 EvalJitWorkerThreads = 0;
1854 if (EvalJitSerdesMode != JitSerdesMode::Off) {
1855 if (ServerMode) {
1856 Logger::Warning("Eval.JitSerdesMode reset from " + jitSerdesMode +
1857 " to off, becasue JitRetranslateAll isn't enabled.");
1859 EvalJitSerdesMode = JitSerdesMode::Off;
1861 EvalJitSerdesFile.clear();
1862 DumpPreciseProfData = false;
1864 EvalJitPGOUseAddrCountedCheck &= addr_encodes_persistency;
1865 HardwareCounter::Init(EvalProfileHWEnable,
1866 url_decode(EvalProfileHWEvents.data(),
1867 EvalProfileHWEvents.size()).toCppString(),
1868 false,
1869 EvalProfileHWExcludeKernel,
1870 EvalProfileHWFastReads,
1871 EvalProfileHWExportInterval);
1873 Config::Bind(EnableIntrinsicsExtension, ini,
1874 config, "Eval.EnableIntrinsicsExtension",
1875 EnableIntrinsicsExtension);
1876 Config::Bind(RecordCodeCoverage, ini, config, "Eval.RecordCodeCoverage");
1877 if (EvalJit && RecordCodeCoverage) {
1878 throw std::runtime_error("Code coverage is not supported with "
1879 "Eval.Jit=true");
1881 Config::Bind(DisableSmallAllocator, ini, config,
1882 "Eval.DisableSmallAllocator", DisableSmallAllocator);
1883 SetArenaSlabAllocBypass(DisableSmallAllocator);
1884 EvalSlabAllocAlign = folly::nextPowTwo(EvalSlabAllocAlign);
1885 EvalSlabAllocAlign = std::min(EvalSlabAllocAlign,
1886 decltype(EvalSlabAllocAlign){4096});
1888 if (RecordCodeCoverage) CheckSymLink = true;
1889 Config::Bind(CodeCoverageOutputFile, ini, config,
1890 "Eval.CodeCoverageOutputFile");
1891 // NB: after we know the value of RepoAuthoritative.
1892 Config::Bind(EnableArgsInBacktraces, ini, config,
1893 "Eval.EnableArgsInBacktraces", !RepoAuthoritative);
1894 Config::Bind(EvalAuthoritativeMode, ini, config, "Eval.AuthoritativeMode",
1895 false);
1897 Config::Bind(CheckCLIClientCommands, ini, config, "Eval.CheckCLIClientCommands", 1);
1898 if (RepoAuthoritative) {
1899 EvalAuthoritativeMode = true;
1902 // Debugger (part of Eval)
1903 Config::Bind(EnableHphpdDebugger, ini, config,
1904 "Eval.Debugger.EnableDebugger");
1905 Config::Bind(EnableDebuggerColor, ini, config,
1906 "Eval.Debugger.EnableDebuggerColor", true);
1907 Config::Bind(EnableDebuggerPrompt, ini, config,
1908 "Eval.Debugger.EnableDebuggerPrompt", true);
1909 Config::Bind(EnableDebuggerServer, ini, config,
1910 "Eval.Debugger.EnableDebuggerServer");
1911 Config::Bind(EnableDebuggerUsageLog, ini, config,
1912 "Eval.Debugger.EnableDebuggerUsageLog");
1913 Config::Bind(DebuggerServerIP, ini, config, "Eval.Debugger.IP");
1914 Config::Bind(DebuggerServerPort, ini, config, "Eval.Debugger.Port", 8089);
1915 Config::Bind(DebuggerDisableIPv6, ini, config,
1916 "Eval.Debugger.DisableIPv6", false);
1917 Config::Bind(DebuggerDefaultSandboxPath, ini, config,
1918 "Eval.Debugger.DefaultSandboxPath");
1919 Config::Bind(DebuggerStartupDocument, ini, config,
1920 "Eval.Debugger.StartupDocument");
1921 Config::Bind(DebuggerSignalTimeout, ini, config,
1922 "Eval.Debugger.SignalTimeout", 1);
1923 Config::Bind(DebuggerDefaultRpcPort, ini, config,
1924 "Eval.Debugger.RPC.DefaultPort", 8083);
1925 DebuggerDefaultRpcAuth =
1926 Config::GetString(ini, config, "Eval.Debugger.RPC.DefaultAuth");
1927 Config::Bind(DebuggerRpcHostDomain, ini, config,
1928 "Eval.Debugger.RPC.HostDomain");
1929 Config::Bind(DebuggerDefaultRpcTimeout, ini, config,
1930 "Eval.Debugger.RPC.DefaultTimeout", 30);
1931 Config::Bind(DebuggerAuthTokenScriptBin, ini, config,
1932 "Eval.Debugger.Auth.TokenScriptBin");
1933 Config::Bind(DebuggerSessionAuthScriptBin, ini, config,
1934 "Eval.Debugger.Auth.SessionAuthScriptBin");
1938 // CodeCache
1939 using jit::CodeCache;
1940 Config::Bind(CodeCache::AHotSize, ini, config, "Eval.JitAHotSize",
1941 ahotDefault());
1942 Config::Bind(CodeCache::ASize, ini, config, "Eval.JitASize", 60 << 20);
1943 Config::Bind(CodeCache::AProfSize, ini, config, "Eval.JitAProfSize",
1944 RuntimeOption::EvalJitPGO ? (64 << 20) : 0);
1945 Config::Bind(CodeCache::AColdSize, ini, config, "Eval.JitAColdSize",
1946 24 << 20);
1947 Config::Bind(CodeCache::AFrozenSize, ini, config, "Eval.JitAFrozenSize",
1948 40 << 20);
1949 Config::Bind(CodeCache::ABytecodeSize, ini, config,
1950 "Eval.JitABytecodeSize", 0);
1951 Config::Bind(CodeCache::GlobalDataSize, ini, config,
1952 "Eval.JitGlobalDataSize", CodeCache::ASize >> 2);
1954 Config::Bind(CodeCache::MapTCHuge, ini, config, "Eval.MapTCHuge",
1955 hugePagesSoundNice());
1957 Config::Bind(CodeCache::TCNumHugeHotMB, ini, config,
1958 "Eval.TCNumHugeHotMB", 64);
1959 Config::Bind(CodeCache::TCNumHugeMainMB, ini, config,
1960 "Eval.TCNumHugeMainMB", 16);
1961 Config::Bind(CodeCache::TCNumHugeColdMB, ini, config,
1962 "Eval.TCNumHugeColdMB", 4);
1964 Config::Bind(CodeCache::AutoTCShift, ini, config, "Eval.JitAutoTCShift", 1);
1967 // Hack Language
1968 Config::Bind(CheckIntOverflow, ini, config,
1969 "Hack.Lang.CheckIntOverflow", 0);
1970 Config::Bind(StrictArrayFillKeys, ini, config,
1971 "Hack.Lang.StrictArrayFillKeys", HackStrictOption::ON);
1972 Config::Bind(EnableFirstClassFunctionPointers, ini, config,
1973 "Hack.Lang.EnableFirstClassFunctionPointers", 0);
1975 Config::Bind(LookForTypechecker, ini, config,
1976 "Hack.Lang.LookForTypechecker", false);
1978 // If you turn off LookForTypechecker, you probably want to turn this off
1979 // too -- basically, make the two look like the same option to external
1980 // users, unless you really explicitly want to set them differently for
1981 // some reason.
1982 Config::Bind(AutoTypecheck, ini, config, "Hack.Lang.AutoTypecheck",
1983 LookForTypechecker);
1984 Config::Bind(EnableClassLevelWhereClauses, ini, config,
1985 "Hack.Lang.EnableClassLevelWhereClauses",
1986 false);
1989 // Options for PHP7 features which break BC. (Features which do not break
1990 // BC don't need options here and can just always be turned on.)
1992 // NB that the "PHP7.all" option is intended to be only a master switch;
1993 // all runtime behavior gating should be based on sub-options (that's why
1994 // it's a file static not a static member of RuntimeOption). Also don't
1995 // forget to update mangleUnitPHP7Options if needed.
1997 // TODO: we may eventually want to make an option which specifies
1998 // directories or filenames to exclude from PHP7 behavior, and so checking
1999 // these may want to be per-file. We originally planned to do this from the
2000 // get-go, but threading that through turns out to be kind of annoying and
2001 // of questionable value, so just doing this for now.
2002 Config::Bind(s_PHP7_master, ini, config, "PHP7.all", s_PHP7_default);
2003 Config::Bind(PHP7_EngineExceptions, ini, config, "PHP7.EngineExceptions",
2004 s_PHP7_master);
2005 Config::Bind(PHP7_NoHexNumerics, ini, config, "PHP7.NoHexNumerics",
2006 s_PHP7_master);
2007 Config::Bind(PHP7_Builtins, ini, config, "PHP7.Builtins", s_PHP7_master);
2008 Config::Bind(PHP7_Substr, ini, config, "PHP7.Substr",
2009 s_PHP7_master);
2010 Config::Bind(PHP7_DisallowUnsafeCurlUploads, ini, config,
2011 "PHP7.DisallowUnsafeCurlUploads", s_PHP7_master);
2014 // Server
2015 Config::Bind(Host, ini, config, "Server.Host");
2016 Config::Bind(DefaultServerNameSuffix, ini, config,
2017 "Server.DefaultServerNameSuffix");
2018 Config::Bind(AlwaysDecodePostDataDefault, ini, config,
2019 "Server.AlwaysDecodePostDataDefault",
2020 AlwaysDecodePostDataDefault);
2021 Config::Bind(ServerType, ini, config, "Server.Type", ServerType);
2022 Config::Bind(ServerIP, ini, config, "Server.IP");
2023 Config::Bind(ServerFileSocket, ini, config, "Server.FileSocket");
2025 #ifdef FACEBOOK
2026 //Do not cause slowness on startup -- except for Facebook
2027 if (GetServerPrimaryIPv4().empty() && GetServerPrimaryIPv6().empty()) {
2028 throw std::runtime_error("Unable to resolve the server's "
2029 "IPv4 or IPv6 address");
2031 #endif
2033 Config::Bind(ServerPort, ini, config, "Server.Port", 80);
2034 Config::Bind(ServerBacklog, ini, config, "Server.Backlog", 128);
2035 Config::Bind(ServerConnectionLimit, ini, config,
2036 "Server.ConnectionLimit", 0);
2037 Config::Bind(ServerThreadCount, ini, config, "Server.ThreadCount",
2038 Process::GetCPUCount() * 2);
2039 Config::Bind(ServerQueueCount, ini, config, "Server.QueueCount",
2040 ServerThreadCount);
2041 Config::Bind(ServerIOThreadCount, ini, config,
2042 "Server.IOThreadCount", 1);
2043 Config::Bind(ServerLegacyBehavior, ini, config, "Server.LegacyBehavior",
2044 ServerLegacyBehavior);
2045 Config::Bind(ServerHugeThreadCount, ini, config,
2046 "Server.HugeThreadCount", 0);
2047 Config::Bind(ServerHugeStackKb, ini, config, "Server.HugeStackSizeKb", 384);
2048 Config::Bind(ServerLoopSampleRate, ini, config,
2049 "Server.LoopSampleRate", 0);
2050 Config::Bind(ServerWarmupThrottleRequestCount, ini, config,
2051 "Server.WarmupThrottleRequestCount",
2052 ServerWarmupThrottleRequestCount);
2053 Config::Bind(ServerWarmupThrottleThreadCount, ini, config,
2054 "Server.WarmupThrottleThreadCount",
2055 Process::GetCPUCount());
2056 Config::Bind(ServerThreadDropCacheTimeoutSeconds, ini, config,
2057 "Server.ThreadDropCacheTimeoutSeconds", 0);
2058 if (Config::GetBool(ini, config, "Server.ThreadJobLIFO")) {
2059 ServerThreadJobLIFOSwitchThreshold = 0;
2061 Config::Bind(ServerThreadJobLIFOSwitchThreshold, ini, config,
2062 "Server.ThreadJobLIFOSwitchThreshold",
2063 ServerThreadJobLIFOSwitchThreshold);
2064 Config::Bind(ServerThreadJobMaxQueuingMilliSeconds, ini, config,
2065 "Server.ThreadJobMaxQueuingMilliSeconds", -1);
2066 Config::Bind(ServerThreadDropStack, ini, config, "Server.ThreadDropStack");
2067 Config::Bind(ServerHttpSafeMode, ini, config, "Server.HttpSafeMode");
2068 Config::Bind(ServerStatCache, ini, config, "Server.StatCache", false);
2069 Config::Bind(ServerFixPathInfo, ini, config, "Server.FixPathInfo", false);
2070 Config::Bind(ServerAddVaryEncoding, ini, config, "Server.AddVaryEncoding",
2071 ServerAddVaryEncoding);
2072 Config::Bind(ServerLogSettingsOnStartup, ini, config,
2073 "Server.LogSettingsOnStartup", false);
2074 Config::Bind(ServerLogReorderProps, ini, config,
2075 "Server.LogReorderProps", false);
2076 Config::Bind(ServerWarmupConcurrently, ini, config,
2077 "Server.WarmupConcurrently", false);
2078 Config::Bind(ServerDedupeWarmupRequests, ini, config,
2079 "Server.DedupeWarmupRequests", false);
2080 Config::Bind(ServerWarmupThreadCount, ini, config,
2081 "Server.WarmupThreadCount", ServerWarmupThreadCount);
2082 Config::Bind(ServerExtendedWarmupThreadCount, ini, config,
2083 "Server.ExtendedWarmup.ThreadCount",
2084 ServerExtendedWarmupThreadCount);
2085 Config::Bind(ServerExtendedWarmupDelaySeconds, ini, config,
2086 "Server.ExtendedWarmup.DelaySeconds",
2087 ServerExtendedWarmupDelaySeconds);
2088 Config::Bind(ServerExtendedWarmupRepeat, ini, config,
2089 "Server.ExtendedWarmup.Repeat", ServerExtendedWarmupRepeat);
2090 Config::Bind(ServerWarmupRequests, ini, config, "Server.WarmupRequests");
2091 Config::Bind(ServerExtendedWarmupRequests, ini, config,
2092 "Server.ExtendedWarmup.Requests");
2093 Config::Bind(ServerCleanupRequest, ini, config, "Server.CleanupRequest");
2094 Config::Bind(ServerInternalWarmupThreads, ini, config,
2095 "Server.InternalWarmupThreads", 0); // 0 = skip
2096 Config::Bind(ServerHighPriorityEndPoints, ini, config,
2097 "Server.HighPriorityEndPoints");
2098 Config::Bind(ServerExitOnBindFail, ini, config, "Server.ExitOnBindFail",
2099 false);
2101 Config::Bind(RequestTimeoutSeconds, ini, config,
2102 "Server.RequestTimeoutSeconds", 0);
2103 Config::Bind(MaxRequestAgeFactor, ini, config, "Server.MaxRequestAgeFactor",
2105 Config::Bind(PspTimeoutSeconds, ini, config, "Server.PspTimeoutSeconds", 0);
2106 Config::Bind(PspCpuTimeoutSeconds, ini, config,
2107 "Server.PspCpuTimeoutSeconds", 0);
2108 Config::Bind(RequestMemoryMaxBytes, ini, config,
2109 "Server.RequestMemoryMaxBytes", (16LL << 30)); // 16GiB
2110 RequestInfo::setOOMKillThreshold(
2111 Config::GetUInt64(ini, config, "Server.RequestMemoryOOMKillBytes",
2112 128ULL << 20));
2113 Config::Bind(RequestHugeMaxBytes, ini, config,
2114 "Server.RequestHugeMaxBytes", (24LL << 20));
2115 Config::Bind(ServerGracefulShutdownWait, ini,
2116 config, "Server.GracefulShutdownWait", 0);
2117 Config::Bind(ServerHarshShutdown, ini, config, "Server.HarshShutdown",
2118 true);
2119 Config::Bind(ServerKillOnTimeout, ini, config, "Server.KillOnTimeout",
2120 true);
2121 Config::Bind(ServerEvilShutdown, ini, config, "Server.EvilShutdown", true);
2122 Config::Bind(ServerPreShutdownWait, ini, config,
2123 "Server.PreShutdownWait", 0);
2124 Config::Bind(ServerShutdownListenWait, ini, config,
2125 "Server.ShutdownListenWait", 0);
2126 Config::Bind(ServerShutdownEOMWait, ini, config,
2127 "Server.ShutdownEOMWait", 0);
2128 Config::Bind(ServerPrepareToStopTimeout, ini, config,
2129 "Server.PrepareToStopTimeout", 240);
2130 Config::Bind(ServerPartialPostStatusCode, ini, config,
2131 "Server.PartialPostStatusCode", -1);
2132 Config::Bind(StopOldServer, ini, config, "Server.StopOld", false);
2133 Config::Bind(OldServerWait, ini, config, "Server.StopOldWait", 30);
2134 Config::Bind(ServerRSSNeededMb, ini, config, "Server.RSSNeededMb", 4096);
2135 Config::Bind(ServerCriticalFreeMb, ini, config,
2136 "Server.CriticalFreeMb", 512);
2137 Config::Bind(CacheFreeFactor, ini, config, "Server.CacheFreeFactor", 50);
2138 if (CacheFreeFactor > 100) CacheFreeFactor = 100;
2139 if (CacheFreeFactor < 0) CacheFreeFactor = 0;
2141 Config::Bind(ServerNextProtocols, ini, config, "Server.SSLNextProtocols");
2142 Config::Bind(ServerEnableH2C, ini, config, "Server.EnableH2C");
2143 extern bool g_brotliUseLocalArena;
2144 Config::Bind(g_brotliUseLocalArena, ini, config,
2145 "Server.BrotliUseLocalArena", g_brotliUseLocalArena);
2146 Config::Bind(BrotliCompressionEnabled, ini, config,
2147 "Server.BrotliCompressionEnabled", -1);
2148 Config::Bind(BrotliChunkedCompressionEnabled, ini, config,
2149 "Server.BrotliChunkedCompressionEnabled", -1);
2150 Config::Bind(BrotliCompressionLgWindowSize, ini, config,
2151 "Server.BrotliCompressionLgWindowSize", 20);
2152 Config::Bind(BrotliCompressionMode, ini, config,
2153 "Server.BrotliCompressionMode", 0);
2154 Config::Bind(BrotliCompressionQuality, ini, config,
2155 "Server.BrotliCompressionQuality", 6);
2156 Config::Bind(ZstdCompressionEnabled, ini, config,
2157 "Server.ZstdCompressionEnabled", -1);
2158 Config::Bind(ZstdCompressor::s_useLocalArena, ini, config,
2159 "Server.ZstdUseLocalArena", ZstdCompressor::s_useLocalArena);
2160 Config::Bind(ZstdCompressionLevel, ini, config,
2161 "Server.ZstdCompressionLevel", 3);
2162 Config::Bind(ZstdChecksumRate, ini, config,
2163 "Server.ZstdChecksumRate", 0);
2164 Config::Bind(GzipCompressionLevel, ini, config,
2165 "Server.GzipCompressionLevel", 3);
2166 Config::Bind(GzipMaxCompressionLevel, ini, config,
2167 "Server.GzipMaxCompressionLevel", 9);
2168 Config::Bind(GzipCompressor::s_useLocalArena, ini, config,
2169 "Server.GzipUseLocalArena", GzipCompressor::s_useLocalArena);
2170 Config::Bind(EnableKeepAlive, ini, config, "Server.EnableKeepAlive", true);
2171 Config::Bind(ExposeHPHP, ini, config, "Server.ExposeHPHP", true);
2172 Config::Bind(ExposeXFBServer, ini, config, "Server.ExposeXFBServer", false);
2173 Config::Bind(ExposeXFBDebug, ini, config, "Server.ExposeXFBDebug", false);
2174 Config::Bind(XFBDebugSSLKey, ini, config, "Server.XFBDebugSSLKey", "");
2175 Config::Bind(ConnectionTimeoutSeconds, ini, config,
2176 "Server.ConnectionTimeoutSeconds", -1);
2177 Config::Bind(EnableOutputBuffering, ini, config,
2178 "Server.EnableOutputBuffering");
2179 Config::Bind(OutputHandler, ini, config, "Server.OutputHandler");
2180 Config::Bind(ImplicitFlush, ini, config, "Server.ImplicitFlush");
2181 Config::Bind(EnableEarlyFlush, ini, config, "Server.EnableEarlyFlush",
2182 true);
2183 Config::Bind(ForceChunkedEncoding, ini, config,
2184 "Server.ForceChunkedEncoding");
2185 Config::Bind(MaxPostSize, ini, config, "Server.MaxPostSize", 100);
2186 MaxPostSize <<= 20;
2187 Config::Bind(AlwaysPopulateRawPostData, ini, config,
2188 "Server.AlwaysPopulateRawPostData", false);
2189 Config::Bind(TakeoverFilename, ini, config, "Server.TakeoverFilename");
2190 Config::Bind(ExpiresActive, ini, config, "Server.ExpiresActive", true);
2191 Config::Bind(ExpiresDefault, ini, config, "Server.ExpiresDefault", 2592000);
2192 if (ExpiresDefault < 0) ExpiresDefault = 2592000;
2193 Config::Bind(DefaultCharsetName, ini, config, "Server.DefaultCharsetName",
2194 "");
2195 Config::Bind(RequestBodyReadLimit, ini, config,
2196 "Server.RequestBodyReadLimit", -1);
2197 Config::Bind(EnableSSL, ini, config, "Server.EnableSSL");
2198 Config::Bind(SSLPort, ini, config, "Server.SSLPort", 443);
2199 Config::Bind(SSLCertificateFile, ini, config, "Server.SSLCertificateFile");
2200 Config::Bind(SSLCertificateKeyFile, ini, config,
2201 "Server.SSLCertificateKeyFile");
2202 Config::Bind(SSLCertificateDir, ini, config, "Server.SSLCertificateDir");
2203 Config::Bind(SSLTicketSeedFile, ini, config, "Server.SSLTicketSeedFile");
2204 Config::Bind(TLSDisableTLS1_2, ini, config, "Server.TLSDisableTLS1_2",
2205 false);
2206 Config::Bind(TLSClientCipherSpec, ini, config,
2207 "Server.TLSClientCipherSpec");
2208 Config::Bind(EnableSSLWithPlainText, ini, config,
2209 "Server.EnableSSLWithPlainText");
2210 Config::Bind(SSLClientAuthLevel, ini, config,
2211 "Server.SSLClientAuthLevel", 0);
2212 if (SSLClientAuthLevel < 0) SSLClientAuthLevel = 0;
2213 if (SSLClientAuthLevel > 2) SSLClientAuthLevel = 2;
2214 Config::Bind(SSLClientCAFile, ini, config, "Server.SSLClientCAFile", "");
2215 if (!SSLClientAuthLevel) {
2216 SSLClientCAFile = "";
2217 } else if (SSLClientCAFile.empty()) {
2218 throw std::runtime_error(
2219 "SSLClientCAFile is required to enable client auth");
2222 Config::Bind(ClientAuthAclIdentity, ini, config,
2223 "Server.ClientAuthAclIdentity", "");
2224 Config::Bind(ClientAuthAclAction, ini, config,
2225 "Server.ClientAuthAclAction", "");
2226 Config::Bind(ClientAuthFailClose, ini, config,
2227 "Server.ClientAuthFailClose", false);
2229 Config::Bind(ClientAuthLogSampleBase, ini, config,
2230 "Server.ClientAuthLogSampleBase", 100);
2231 if (ClientAuthLogSampleBase < 1) {
2232 ClientAuthLogSampleBase = 1;
2235 Config::Bind(SSLClientAuthLoggingSampleRatio, ini, config,
2236 "Server.SSLClientAuthLoggingSampleRatio", 0);
2237 if (SSLClientAuthLoggingSampleRatio < 0) {
2238 SSLClientAuthLoggingSampleRatio = 0;
2240 if (SSLClientAuthLoggingSampleRatio > ClientAuthLogSampleBase) {
2241 SSLClientAuthLoggingSampleRatio = ClientAuthLogSampleBase;
2244 Config::Bind(ClientAuthSuccessLogSampleRatio, ini, config,
2245 "Server.ClientAuthSuccessLogSampleRatio", 0);
2246 if (ClientAuthSuccessLogSampleRatio <
2247 SSLClientAuthLoggingSampleRatio) {
2248 ClientAuthSuccessLogSampleRatio = SSLClientAuthLoggingSampleRatio;
2250 if (ClientAuthSuccessLogSampleRatio > ClientAuthLogSampleBase) {
2251 ClientAuthSuccessLogSampleRatio = ClientAuthLogSampleBase;
2254 Config::Bind(ClientAuthFailureLogSampleRatio, ini, config,
2255 "Server.ClientAuthFailureLogSampleRatio", 0);
2256 if (ClientAuthFailureLogSampleRatio <
2257 SSLClientAuthLoggingSampleRatio) {
2258 ClientAuthFailureLogSampleRatio = SSLClientAuthLoggingSampleRatio;
2260 if (ClientAuthFailureLogSampleRatio > ClientAuthLogSampleBase) {
2261 ClientAuthFailureLogSampleRatio = ClientAuthLogSampleBase;
2264 // SourceRoot has been default to: Process::GetCurrentDirectory() + '/'
2265 auto defSourceRoot = SourceRoot;
2266 Config::Bind(SourceRoot, ini, config, "Server.SourceRoot", SourceRoot);
2267 SourceRoot = FileUtil::normalizeDir(SourceRoot);
2268 if (SourceRoot.empty()) {
2269 SourceRoot = defSourceRoot;
2271 FileCache::SourceRoot = SourceRoot;
2273 Config::Bind(IncludeSearchPaths, ini, config, "Server.IncludeSearchPaths");
2274 for (unsigned int i = 0; i < IncludeSearchPaths.size(); i++) {
2275 IncludeSearchPaths[i] = FileUtil::normalizeDir(IncludeSearchPaths[i]);
2277 IncludeSearchPaths.insert(IncludeSearchPaths.begin(), ".");
2279 Config::Bind(AutoloadEnabled, ini, config, "Autoload.Enabled", false);
2280 Config::Bind(AutoloadDBPath, ini, config, "Autoload.DBPath");
2282 Config::Bind(FileCache, ini, config, "Server.FileCache");
2283 Config::Bind(DefaultDocument, ini, config, "Server.DefaultDocument",
2284 "index.php");
2285 Config::Bind(GlobalDocument, ini, config, "Server.GlobalDocument");
2286 Config::Bind(ErrorDocument404, ini, config, "Server.ErrorDocument404");
2287 normalizePath(ErrorDocument404);
2288 Config::Bind(ForbiddenAs404, ini, config, "Server.ForbiddenAs404");
2289 Config::Bind(ErrorDocument500, ini, config, "Server.ErrorDocument500");
2290 normalizePath(ErrorDocument500);
2291 Config::Bind(FatalErrorMessage, ini, config, "Server.FatalErrorMessage");
2292 FontPath = FileUtil::normalizeDir(
2293 Config::GetString(ini, config, "Server.FontPath"));
2294 Config::Bind(EnableStaticContentFromDisk, ini, config,
2295 "Server.EnableStaticContentFromDisk", true);
2296 Config::Bind(EnableOnDemandUncompress, ini, config,
2297 "Server.EnableOnDemandUncompress", true);
2298 Config::Bind(EnableStaticContentMMap, ini, config,
2299 "Server.EnableStaticContentMMap", true);
2300 if (EnableStaticContentMMap) {
2301 EnableOnDemandUncompress = true;
2303 Config::Bind(Utf8izeReplace, ini, config, "Server.Utf8izeReplace", true);
2305 Config::Bind(RequestInitFunction, ini, config,
2306 "Server.RequestInitFunction");
2307 Config::Bind(RequestInitDocument, ini, config,
2308 "Server.RequestInitDocument");
2309 Config::Bind(SafeFileAccess, ini, config, "Server.SafeFileAccess");
2310 Config::Bind(AllowedDirectories, ini, config, "Server.AllowedDirectories");
2311 Config::Bind(WhitelistExec, ini, config, "Server.WhitelistExec");
2312 Config::Bind(WhitelistExecWarningOnly, ini, config,
2313 "Server.WhitelistExecWarningOnly");
2314 Config::Bind(AllowedExecCmds, ini, config, "Server.AllowedExecCmds");
2315 Config::Bind(UnserializationWhitelistCheck, ini, config,
2316 "Server.UnserializationWhitelistCheck", false);
2317 Config::Bind(UnserializationWhitelistCheckWarningOnly, ini, config,
2318 "Server.UnserializationWhitelistCheckWarningOnly", true);
2319 Config::Bind(UnserializationBigMapThreshold, ini, config,
2320 "Server.UnserializationBigMapThreshold", 1 << 16);
2321 Config::Bind(AllowedFiles, ini, config, "Server.AllowedFiles");
2322 Config::Bind(ForbiddenFileExtensions, ini, config,
2323 "Server.ForbiddenFileExtensions");
2324 Config::Bind(LockCodeMemory, ini, config, "Server.LockCodeMemory", false);
2325 Config::Bind(MaxArrayChain, ini, config, "Server.MaxArrayChain", INT_MAX);
2326 if (MaxArrayChain != INT_MAX) {
2327 // MixedArray needs a higher threshold to avoid false-positives.
2328 // (and we always use MixedArray)
2329 MaxArrayChain *= 2;
2332 Config::Bind(WarnOnCollectionToArray, ini, config,
2333 "Server.WarnOnCollectionToArray", false);
2334 Config::Bind(UseDirectCopy, ini, config, "Server.UseDirectCopy", false);
2335 Config::Bind(AlwaysUseRelativePath, ini, config,
2336 "Server.AlwaysUseRelativePath", false);
2338 // Server Upload
2339 Config::Bind(UploadMaxFileSize, ini, config,
2340 "Server.Upload.UploadMaxFileSize", 100);
2341 UploadMaxFileSize <<= 20;
2342 Config::Bind(UploadTmpDir, ini, config, "Server.Upload.UploadTmpDir",
2343 "/tmp");
2344 Config::Bind(EnableFileUploads, ini, config,
2345 "Server.Upload.EnableFileUploads", true);
2346 Config::Bind(MaxFileUploads, ini, config, "Server.Upload.MaxFileUploads",
2347 20);
2348 Config::Bind(EnableUploadProgress, ini, config,
2349 "Server.Upload.EnableUploadProgress");
2350 Config::Bind(Rfc1867Freq, ini, config, "Server.Upload.Rfc1867Freq",
2351 256 * 1024);
2352 if (Rfc1867Freq < 0) Rfc1867Freq = 256 * 1024;
2353 Config::Bind(Rfc1867Prefix, ini, config, "Server.Upload.Rfc1867Prefix",
2354 "vupload_");
2355 Config::Bind(Rfc1867Name, ini, config, "Server.Upload.Rfc1867Name",
2356 "video_ptoken");
2358 Config::Bind(ImageMemoryMaxBytes, ini, config,
2359 "Server.ImageMemoryMaxBytes", 0);
2360 if (ImageMemoryMaxBytes == 0) {
2361 ImageMemoryMaxBytes = UploadMaxFileSize * 2;
2363 Config::Bind(LightProcessFilePrefix, ini, config,
2364 "Server.LightProcessFilePrefix", "./lightprocess");
2365 Config::Bind(LightProcessCount, ini, config,
2366 "Server.LightProcessCount", 0);
2367 Config::Bind(ForceServerNameToHeader, ini, config,
2368 "Server.ForceServerNameToHeader");
2369 Config::Bind(AllowDuplicateCookies, ini, config,
2370 "Server.AllowDuplicateCookies", false);
2371 Config::Bind(PathDebug, ini, config, "Server.PathDebug", false);
2372 Config::Bind(ServerUser, ini, config, "Server.User", "");
2373 Config::Bind(AllowRunAsRoot, ini, config, "Server.AllowRunAsRoot", false);
2376 VirtualHost::SortAllowedDirectories(AllowedDirectories);
2378 auto vh_callback = [] (const IniSettingMap &ini_vh, const Hdf &hdf_vh,
2379 const std::string &ini_vh_key) {
2380 if (VirtualHost::IsDefault(ini_vh, hdf_vh, ini_vh_key)) {
2381 VirtualHost::GetDefault().init(ini_vh, hdf_vh, ini_vh_key);
2382 VirtualHost::GetDefault().addAllowedDirectories(AllowedDirectories);
2383 } else {
2384 auto host = std::make_shared<VirtualHost>(ini_vh, hdf_vh, ini_vh_key);
2385 host->addAllowedDirectories(AllowedDirectories);
2386 VirtualHosts.push_back(host);
2389 // Virtual Hosts have to be iterated in order. Because only the first
2390 // one that matches in the VirtualHosts vector gets applied and used.
2391 // Hdf's and ini (via Variant arrays) internal storage handles ordering
2392 // naturally (as specified top to bottom in the file and left to right on
2393 // the command line.
2394 Config::Iterate(vh_callback, ini, config, "VirtualHost");
2395 LowestMaxPostSize = VirtualHost::GetLowestMaxPostSize();
2398 // IpBlocks
2399 IpBlocks = std::make_shared<IpBlockMap>(ini, config);
2402 ReadSatelliteInfo(ini, config, SatelliteServerInfos,
2403 XboxPassword, XboxPasswords);
2406 // Xbox
2407 Config::Bind(XboxServerThreadCount, ini, config,
2408 "Xbox.ServerInfo.ThreadCount", 10);
2409 Config::Bind(XboxServerMaxQueueLength, ini, config,
2410 "Xbox.ServerInfo.MaxQueueLength", INT_MAX);
2411 if (XboxServerMaxQueueLength < 0) XboxServerMaxQueueLength = INT_MAX;
2412 Config::Bind(XboxServerPort, ini, config, "Xbox.ServerInfo.Port", 0);
2413 Config::Bind(XboxDefaultLocalTimeoutMilliSeconds, ini, config,
2414 "Xbox.DefaultLocalTimeoutMilliSeconds", 500);
2415 Config::Bind(XboxDefaultRemoteTimeoutSeconds, ini, config,
2416 "Xbox.DefaultRemoteTimeoutSeconds", 5);
2417 Config::Bind(XboxServerInfoMaxRequest, ini, config,
2418 "Xbox.ServerInfo.MaxRequest", 500);
2419 Config::Bind(XboxServerInfoDuration, ini, config,
2420 "Xbox.ServerInfo.MaxDuration", 120);
2421 Config::Bind(XboxServerInfoReqInitFunc, ini, config,
2422 "Xbox.ServerInfo.RequestInitFunction", "");
2423 Config::Bind(XboxServerInfoReqInitDoc, ini, config,
2424 "Xbox.ServerInfo.RequestInitDocument", "");
2425 Config::Bind(XboxServerInfoAlwaysReset, ini, config,
2426 "Xbox.ServerInfo.AlwaysReset", false);
2427 Config::Bind(XboxServerLogInfo, ini, config, "Xbox.ServerInfo.LogInfo",
2428 false);
2429 Config::Bind(XboxProcessMessageFunc, ini, config, "Xbox.ProcessMessageFunc",
2430 "xbox_process_message");
2433 // Pagelet Server
2434 Config::Bind(PageletServerThreadCount, ini, config,
2435 "PageletServer.ThreadCount", 0);
2436 Config::Bind(PageletServerHugeThreadCount, ini, config,
2437 "PageletServer.HugeThreadCount", 0);
2438 Config::Bind(PageletServerThreadDropStack, ini, config,
2439 "PageletServer.ThreadDropStack");
2440 Config::Bind(PageletServerThreadDropCacheTimeoutSeconds, ini, config,
2441 "PageletServer.ThreadDropCacheTimeoutSeconds", 0);
2442 Config::Bind(PageletServerQueueLimit, ini, config,
2443 "PageletServer.QueueLimit", 0);
2446 // Static File
2448 hphp_string_imap<std::string> staticFileDefault;
2449 staticFileDefault["css"] = "text/css";
2450 staticFileDefault["gif"] = "image/gif";
2451 staticFileDefault["html"] = "text/html";
2452 staticFileDefault["jpeg"] = "image/jpeg";
2453 staticFileDefault["jpg"] = "image/jpeg";
2454 staticFileDefault["mp3"] = "audio/mpeg";
2455 staticFileDefault["png"] = "image/png";
2456 staticFileDefault["tif"] = "image/tiff";
2457 staticFileDefault["tiff"] = "image/tiff";
2458 staticFileDefault["txt"] = "text/plain";
2459 staticFileDefault["zip"] = "application/zip";
2461 Config::Bind(StaticFileExtensions, ini, config, "StaticFile.Extensions",
2462 staticFileDefault);
2464 auto matches_callback = [](const IniSettingMap& ini_m, const Hdf& hdf_m,
2465 const std::string& /*ini_m_key*/) {
2466 FilesMatches.push_back(std::make_shared<FilesMatch>(ini_m, hdf_m));
2468 Config::Iterate(matches_callback, ini, config, "StaticFile.FilesMatch");
2471 // PhpFile
2472 Config::Bind(PhpFileExtensions, ini, config, "PhpFile.Extensions");
2475 // Admin Server
2476 Config::Bind(AdminServerIP, ini, config, "AdminServer.IP", ServerIP);
2477 Config::Bind(AdminServerPort, ini, config, "AdminServer.Port", 0);
2478 Config::Bind(AdminThreadCount, ini, config, "AdminServer.ThreadCount", 1);
2479 Config::Bind(AdminServerEnableSSLWithPlainText, ini, config,
2480 "AdminServer.EnableSSLWithPlainText", false);
2481 Config::Bind(AdminServerStatsNeedPassword, ini, config,
2482 "AdminServer.StatsNeedPassword", AdminServerStatsNeedPassword);
2483 AdminPassword = Config::GetString(ini, config, "AdminServer.Password");
2484 AdminPasswords = Config::GetSet(ini, config, "AdminServer.Passwords");
2485 HashedAdminPasswords =
2486 Config::GetSet(ini, config, "AdminServer.HashedPasswords");
2489 // Proxy
2490 Config::Bind(ProxyOriginRaw, ini, config, "Proxy.Origin");
2491 Config::Bind(ProxyPercentageRaw, ini, config, "Proxy.Percentage", 0);
2492 Config::Bind(ProxyRetry, ini, config, "Proxy.Retry", 3);
2493 Config::Bind(UseServeURLs, ini, config, "Proxy.ServeURLs");
2494 Config::Bind(ServeURLs, ini, config, "Proxy.ServeURLs");
2495 Config::Bind(UseProxyURLs, ini, config, "Proxy.ProxyURLs");
2496 Config::Bind(ProxyURLs, ini, config, "Proxy.ProxyURLs");
2497 Config::Bind(ProxyPatterns, ini, config, "Proxy.ProxyPatterns");
2500 // Http
2501 Config::Bind(HttpDefaultTimeout, ini, config, "Http.DefaultTimeout", 30);
2502 Config::Bind(HttpSlowQueryThreshold, ini, config, "Http.SlowQueryThreshold",
2503 5000);
2506 // Debug
2508 Config::Bind(NativeStackTrace, ini, config, "Debug.NativeStackTrace");
2509 StackTrace::Enabled = NativeStackTrace;
2510 Config::Bind(ServerErrorMessage, ini, config, "Debug.ServerErrorMessage");
2511 Config::Bind(RecordInput, ini, config, "Debug.RecordInput");
2512 Config::Bind(ClearInputOnSuccess, ini, config, "Debug.ClearInputOnSuccess",
2513 true);
2514 Config::Bind(ProfilerOutputDir, ini, config, "Debug.ProfilerOutputDir",
2515 "/tmp");
2516 Config::Bind(CoreDumpEmail, ini, config, "Debug.CoreDumpEmail");
2517 Config::Bind(CoreDumpReport, ini, config, "Debug.CoreDumpReport", true);
2518 if (CoreDumpReport) {
2519 install_crash_reporter();
2521 // Binding default dependenant on whether we are using an OSS build or
2522 // not, and that is set at initialization time of CoreDumpReportDirectory.
2523 Config::Bind(CoreDumpReportDirectory, ini, config,
2524 "Debug.CoreDumpReportDirectory", CoreDumpReportDirectory);
2525 std::ostringstream stack_trace_stream;
2526 stack_trace_stream << CoreDumpReportDirectory << "/stacktrace."
2527 << (int64_t)getpid() << ".log";
2528 StackTraceFilename = stack_trace_stream.str();
2530 Config::Bind(StackTraceTimeout, ini, config, "Debug.StackTraceTimeout", 0);
2531 Config::Bind(RemoteTraceOutputDir, ini, config,
2532 "Debug.RemoteTraceOutputDir", "/tmp");
2533 Config::Bind(TraceFunctions, ini, config,
2534 "Debug.TraceFunctions", TraceFunctions);
2535 Config::Bind(TraceFuncId, ini, config, "Debug.TraceFuncId", TraceFuncId);
2538 // Stats
2539 Config::Bind(EnableStats, ini, config, "Stats.Enable",
2540 false); // main switch
2541 Config::Bind(EnableAPCStats, ini, config, "Stats.APC", false);
2542 Config::Bind(EnableWebStats, ini, config, "Stats.Web");
2543 Config::Bind(EnableMemoryStats, ini, config, "Stats.Memory");
2544 Config::Bind(EnableSQLStats, ini, config, "Stats.SQL");
2545 Config::Bind(EnableSQLTableStats, ini, config, "Stats.SQLTable");
2546 Config::Bind(EnableNetworkIOStatus, ini, config, "Stats.NetworkIO");
2547 Config::Bind(StatsXSL, ini, config, "Stats.XSL");
2548 Config::Bind(StatsXSLProxy, ini, config, "Stats.XSLProxy");
2549 Config::Bind(StatsSlotDuration, ini, config, "Stats.SlotDuration", 10 * 60);
2550 Config::Bind(StatsMaxSlot, ini, config, "Stats.MaxSlot",
2551 12 * 6); // 12 hours
2552 StatsSlotDuration = std::max(1u, StatsSlotDuration);
2553 StatsMaxSlot = std::max(2u, StatsMaxSlot);
2554 Config::Bind(EnableHotProfiler, ini, config, "Stats.EnableHotProfiler",
2555 true);
2556 Config::Bind(ProfilerTraceBuffer, ini, config, "Stats.ProfilerTraceBuffer",
2557 2000000);
2558 Config::Bind(ProfilerTraceExpansion, ini, config,
2559 "Stats.ProfilerTraceExpansion", 1.2);
2560 Config::Bind(ProfilerMaxTraceBuffer, ini, config,
2561 "Stats.ProfilerMaxTraceBuffer", 0);
2562 Config::Bind(TrackPerUnitMemory, ini, config,
2563 "Stats.TrackPerUnitMemory", false);
2566 Config::Bind(ServerVariables, ini, config, "ServerVariables");
2567 Config::Bind(EnvVariables, ini, config, "EnvVariables");
2570 // Sandbox
2571 Config::Bind(SandboxMode, ini, config, "Sandbox.SandboxMode");
2572 Config::Bind(SandboxPattern, ini, config, "Sandbox.Pattern");
2573 SandboxPattern = format_pattern(SandboxPattern, true);
2574 Config::Bind(SandboxHome, ini, config, "Sandbox.Home");
2575 Config::Bind(SandboxFallback, ini, config, "Sandbox.Fallback");
2576 Config::Bind(SandboxConfFile, ini, config, "Sandbox.ConfFile");
2577 Config::Bind(SandboxFromCommonRoot, ini, config, "Sandbox.FromCommonRoot");
2578 Config::Bind(SandboxDirectoriesRoot, ini, config,
2579 "Sandbox.DirectoriesRoot");
2580 Config::Bind(SandboxLogsRoot, ini, config, "Sandbox.LogsRoot");
2581 Config::Bind(SandboxServerVariables, ini, config,
2582 "Sandbox.ServerVariables");
2583 Config::Bind(SandboxDefaultUserFile, ini, config,
2584 "Sandbox.DefaultUserFile");
2585 Config::Bind(SandboxHostAlias, ini, config, "Sandbox.HostAlias");
2588 // Mail
2589 Config::Bind(SendmailPath, ini, config, "Mail.SendmailPath",
2590 "/usr/lib/sendmail -t -i");
2591 Config::Bind(MailForceExtraParameters, ini, config,
2592 "Mail.ForceExtraParameters");
2595 // Preg
2596 Config::Bind(PregBacktraceLimit, ini, config, "Preg.BacktraceLimit",
2597 1000000);
2598 Config::Bind(PregRecursionLimit, ini, config, "Preg.RecursionLimit",
2599 100000);
2600 Config::Bind(EnablePregErrorLog, ini, config, "Preg.ErrorLog", true);
2603 // SimpleXML
2604 Config::Bind(SimpleXMLEmptyNamespaceMatchesAll, ini, config,
2605 "SimpleXML.EmptyNamespaceMatchesAll", false);
2607 #ifdef FACEBOOK
2609 // Fb303Server
2610 Config::Bind(EnableFb303Server, ini, config, "Fb303Server.Enable",
2611 EnableFb303Server);
2612 Config::Bind(Fb303ServerPort, ini, config, "Fb303Server.Port", 0);
2613 Config::Bind(Fb303ServerThreadStackSizeMb, ini, config,
2614 "Fb303Server.ThreadStackSizeMb", 8);
2615 Config::Bind(Fb303ServerWorkerThreads, ini, config,
2616 "Fb303Server.WorkerThreads", 1);
2617 Config::Bind(Fb303ServerPoolThreads, ini, config, "Fb303Server.PoolThreads",
2620 #endif
2623 // Xenon
2624 Config::Bind(XenonPeriodSeconds, ini, config, "Xenon.Period", 0.0);
2625 Config::Bind(XenonRequestFreq, ini, config, "Xenon.RequestFreq", 1);
2626 Config::Bind(XenonForceAlwaysOn, ini, config, "Xenon.ForceAlwaysOn", false);
2629 // Strobelight
2630 Config::Bind(StrobelightEnabled, ini, config, "Strobelight.Enabled", false);
2633 // Profiling
2634 Config::Bind(SetProfileNullThisObject, ini, config,
2635 "SetProfile.NullThisObject", true);
2638 // We directly read zend.assertions here, so that we can get its INI value
2639 // in order to know how we should emit bytecode. We don't actually Bind the
2640 // option here though, since its runtime value can be changed and is per
2641 // request. (We prevent its value from changing at runtime between values
2642 // that would affect byecode emission.)
2643 Variant v;
2644 bool b = IniSetting::GetSystem("zend.assertions", v);
2645 if (b) RuntimeOption::AssertEmitted = v.toInt64() >= 0;
2648 Config::Bind(TzdataSearchPaths, ini, config, "TzdataSearchPaths");
2650 Config::Bind(CustomSettings, ini, config, "CustomSettings");
2652 // Run initializers depedent on options, e.g., resizing atomic maps/vectors.
2653 refineStaticStringTableSize();
2654 InitFiniNode::ProcessPostRuntimeOptions();
2655 always_assert(Func::getFuncVec().size() == RuntimeOption::EvalFuncCountHint);
2657 // **************************************************************************
2658 // DANGER
2660 // Do not bind any PHP_INI_ALL or PHP_INI_USER settings here! These settings
2661 // are process-wide, while those need to be thread-local since they are
2662 // per-request. They should go into RequestInjectionData. Getting this wrong
2663 // will cause subtle breakage -- in particular, it probably will not show up
2664 // in CLI mode, since everything there tends to be single theaded.
2666 // Per-dir INI settings are bound here, but that seems really questionable
2667 // since they can change per request too. TODO(#7757602) this should be
2668 // investigated.
2669 // **************************************************************************
2671 // Enables the hotfixing of a bug that occurred with D1797805 where
2672 // per request user settings (like upload_max_filesize) were not able to be
2673 // accessed on a server request any longer. The longer term fix is in review
2674 // D2099778, but we want that to simmer in Master for a while and we need
2675 // a hotfix for our current 3.6 LTS (Github Issue #4993)
2676 Config::Bind(EnableZendIniCompat, ini, config, "Eval.EnableZendIniCompat",
2677 true);
2678 // Language and Misc Configuration Options
2679 IniSetting::Bind(IniSetting::CORE, IniSetting::PHP_INI_ONLY, "expose_php",
2680 &RuntimeOption::ExposeHPHP);
2681 IniSetting::Bind(IniSetting::CORE, IniSetting::PHP_INI_PERDIR,
2682 "auto_prepend_file", &RuntimeOption::AutoPrependFile);
2683 IniSetting::Bind(IniSetting::CORE, IniSetting::PHP_INI_PERDIR,
2684 "auto_append_file", &RuntimeOption::AutoAppendFile);
2686 // Data Handling
2687 IniSetting::Bind(IniSetting::CORE, IniSetting::PHP_INI_PERDIR,
2688 "post_max_size",
2689 IniSetting::SetAndGet<int64_t>(
2690 nullptr,
2691 []() {
2692 return VirtualHost::GetMaxPostSize();
2695 &RuntimeOption::MaxPostSize);
2696 IniSetting::Bind(IniSetting::CORE, IniSetting::PHP_INI_PERDIR,
2697 "always_populate_raw_post_data",
2698 &RuntimeOption::AlwaysPopulateRawPostData);
2700 // Paths and Directories
2701 IniSetting::Bind(IniSetting::CORE, IniSetting::PHP_INI_SYSTEM,
2702 "doc_root", &RuntimeOption::SourceRoot);
2703 IniSetting::Bind(IniSetting::CORE, IniSetting::PHP_INI_SYSTEM,
2704 "sendmail_path", &RuntimeOption::SendmailPath);
2706 // FastCGI
2707 IniSetting::Bind(IniSetting::CORE, IniSetting::PHP_INI_ONLY,
2708 "pid", &RuntimeOption::PidFile);
2710 // File Uploads
2711 IniSetting::Bind(IniSetting::CORE, IniSetting::PHP_INI_SYSTEM,
2712 "file_uploads", "true",
2713 &RuntimeOption::EnableFileUploads);
2714 IniSetting::Bind(IniSetting::CORE, IniSetting::PHP_INI_SYSTEM,
2715 "upload_tmp_dir", &RuntimeOption::UploadTmpDir);
2716 IniSetting::Bind(IniSetting::CORE, IniSetting::PHP_INI_PERDIR,
2717 "upload_max_filesize",
2718 IniSetting::SetAndGet<std::string>(
2719 [](const std::string& value) {
2720 return ini_on_update(
2721 value, RuntimeOption::UploadMaxFileSize);
2723 []() {
2724 return convert_long_to_bytes(
2725 VirtualHost::GetUploadMaxFileSize());
2728 // Filesystem and Streams Configuration Options
2729 IniSetting::Bind(IniSetting::CORE, IniSetting::PHP_INI_SYSTEM,
2730 "allow_url_fopen",
2731 IniSetting::SetAndGet<std::string>(
2732 [](const std::string& /*value*/) { return false; },
2733 []() { return "1"; }));
2735 // HPHP specific
2736 IniSetting::Bind(IniSetting::CORE, IniSetting::PHP_INI_NONE,
2737 "hphp.compiler_id",
2738 IniSetting::SetAndGet<std::string>(
2739 [](const std::string& /*value*/) { return false; },
2740 []() { return compilerId().begin(); }));
2741 IniSetting::Bind(IniSetting::CORE, IniSetting::PHP_INI_NONE,
2742 "hphp.compiler_version",
2743 IniSetting::SetAndGet<std::string>(
2744 [](const std::string& /*value*/) { return false; },
2745 []() { return getHphpCompilerVersion(); }));
2746 IniSetting::Bind(IniSetting::CORE, IniSetting::PHP_INI_NONE,
2747 "hphp.cli_server_api_version",
2748 IniSetting::SetAndGet<uint64_t>(
2749 [](const uint64_t /*value*/) { return false; },
2750 []() { return cli_server_api_version(); }));
2751 IniSetting::Bind(
2752 IniSetting::CORE, IniSetting::PHP_INI_NONE, "hphp.build_id",
2753 IniSetting::SetAndGet<std::string>(
2754 [](const std::string& /*value*/) { return false; }, nullptr),
2755 &RuntimeOption::BuildId);
2756 IniSetting::Bind(IniSetting::CORE, IniSetting::PHP_INI_SYSTEM,
2757 "notice_frequency",
2758 &RuntimeOption::NoticeFrequency);
2759 IniSetting::Bind(IniSetting::CORE, IniSetting::PHP_INI_SYSTEM,
2760 "warning_frequency",
2761 &RuntimeOption::WarningFrequency);
2762 IniSetting::Bind(IniSetting::CORE, IniSetting::PHP_INI_ONLY,
2763 "hhvm.build_type",
2764 IniSetting::SetAndGet<std::string>(
2765 [](const std::string&) {
2766 return false;
2768 []() {
2769 return s_hhvm_build_type.c_str();
2773 // Extensions
2774 Config::Bind(RuntimeOption::ExtensionDir, ini, config, "extension_dir",
2775 RuntimeOption::ExtensionDir, false);
2776 Config::Bind(RuntimeOption::DynamicExtensionPath, ini,
2777 config, "DynamicExtensionPath",
2778 RuntimeOption::DynamicExtensionPath);
2779 Config::Bind(RuntimeOption::Extensions, ini, config, "extensions");
2780 Config::Bind(RuntimeOption::DynamicExtensions, ini,
2781 config, "DynamicExtensions");
2783 ExtensionRegistry::moduleLoad(ini, config);
2784 initialize_apc();
2786 if (TraceFunctions.size() || TraceFuncId != InvalidFuncId) {
2787 Trace::ensureInit(getTraceOutputFile());
2790 // Bespoke array-likes
2792 // We don't support provenance for bespoke array-likes, so don't construct
2793 // any at runtime if we're logging provenance instrumentation results.
2794 if (RO::EvalBespokeArrayLikeMode > 0 &&
2795 (RO::EvalArrayProvenance || RO::EvalLogArrayProvenance)) {
2796 RO::EvalBespokeArrayLikeMode = 0;
2799 // If we're going to construct bespoke array-likes at runtime, ensure that
2800 // we JIT checks for these types as well. We support JIT-ing these checks
2801 // even if there are no runtime bespokes as way to test our guard logic.
2802 if (RO::EvalBespokeArrayLikeMode == 0) {
2803 specializeVanillaDestructors();
2804 bespoke::setLoggingEnabled(false);
2805 } else {
2806 bespoke::setLoggingEnabled(true);
2809 // Hack Array Compats
2811 if (!RuntimeOption::EvalEmitClsMethPointers) {
2812 RuntimeOption::EvalIsCompatibleClsMethType = false;
2815 if (RuntimeOption::EvalArrayProvenance) {
2816 RuntimeOption::EvalJitForceVMRegSync = true;
2819 // Initialize defaults for repo-specific parser configuration options.
2820 RepoOptions::setDefaults(config, ini);
2823 ///////////////////////////////////////////////////////////////////////////////