2 +----------------------------------------------------------------------+
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"
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__)
85 #include <asm/hwcap.h>
89 #define st_mtim st_mtimespec
90 #define st_ctim st_ctimespec
94 ///////////////////////////////////////////////////////////////////////////////
96 bool RepoOptions::s_init
{false};
97 RepoOptions
RepoOptions::s_defaults
;
102 const static bool s_PHP7_default
= false;
104 const static bool s_PHP7_default
= true;
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
) {
120 s
+= folly::to
<std::string
>(map
.size());
122 for (auto& par
: map
) {
123 s
+= par
.first
+ '\0' + par
.second
+ '\0';
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
);
137 RepoOptions::StringMap
& map
,
138 const RepoOptions::StringMap
& dv
140 Hdf config
= hdf
[name
];
141 if (config
.exists() && !config
.isEmpty()) config
.configGet(map
);
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
;
164 folly::dynamic
toIniValue(const std::string
& str
) {
168 struct CachedRepoOptions
{
169 CachedRepoOptions() = default;
170 explicit CachedRepoOptions(RepoOptions
&& opts
)
171 : options(new RepoOptions(std::move(opts
)))
173 CachedRepoOptions(const CachedRepoOptions
& opts
)
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
; });
191 static bool isChanged(const RepoOptions
* opts
, struct stat s
) {
192 auto const o
= opts
->stat();
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
; });
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
<
222 RepoOptionCache s_repoOptionCache
;
225 bool walkDirTree(std::string fpath
, F func
) {
226 const char* filename
= ".hhvmconfig.hdf";
228 auto const off
= fpath
.rfind('/');
229 if (off
== std::string::npos
) return false;
234 if (func(fpath
)) return true;
237 } while (!fpath
.empty() && fpath
!= "/");
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())) {
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
)) {
280 RepoOptions newOpts
{path
.data()};
282 return rpathAcc
->second
.update(std::move(newOpts
));
285 auto const test
= [&] (const std::string
& path
) -> const RepoOptions
* {
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
);
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,
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
) {
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
);
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)
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)
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;
398 const RepoOptions
& RepoOptions::defaults() {
399 always_assert(s_init
);
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",
408 it
= AliasedNamespaces
.erase(it
);
412 while (it
->second
.size() && it
->second
[0] == '\\') {
413 it
->second
= it
->second
.substr(1);
420 RepoOptions::RepoOptions(const char* file
) : m_path(file
) {
421 always_assert(s_init
);
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);
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, \
440 #define E(_, n, ...) hdfExtract(autoloadConfig, "Eval." #n, n, s_defaults.n);
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);
466 void RepoOptions::setDefaults(const Hdf
& hdf
, const IniSettingMap
& ini
) {
467 always_assert(!s_init
);
468 s_defaults
.initDefaults(hdf
, ini
);
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)
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;
803 bool RuntimeOption::DisableSmallAllocator
= true;
805 bool RuntimeOption::DisableSmallAllocator
= false;
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
;
831 std::string
RuntimeOption::ExtensionDir
= "";
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;
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() {
855 if (EnableShortTags
) type
|= Scanner::AllowShortTags
;
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() {
873 static inline bool pgoDefault() {
874 #ifdef HHVM_NO_DEFAULT_PGO
881 static inline bool eagerGcDefault() {
889 static inline std::string
hackCompilerArgsDefault() {
890 return "--daemon --dump-symbol-refs";
893 static inline std::string
hackCompilerCommandDefault() {
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
905 hackc
= HACKC_FALLBACK_PATH
;
906 if (::access(hackc
.data(), X_OK
) != 0) {
912 return folly::sformat(
915 hackCompilerArgsDefault()
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
:
936 case ProcessorFamily::Unknown
:
942 static inline bool armLseDefault() {
943 #if defined (__linux__) && defined (__aarch64__) && defined (HWCAP_ATOMICS)
944 return (getauxval(AT_HWCAP
) & HWCAP_ATOMICS
) != 0;
950 static inline bool evalJitDefault() {
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
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
)};
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 {};
1046 if (!folly::readFile(file
.c_str(), user
) || user
.empty()) return {};
1051 bool RuntimeOption::ReadPerUserSettings(const folly::fs::path
& confFileName
,
1052 IniSettingMap
& ini
, Hdf
& config
) {
1054 Config::ParseConfigFile(confFileName
.native(), ini
, config
, false);
1056 } catch (HdfException
& e
) {
1057 Logger::Error("%s ignored: %s", confFileName
.native().c_str(),
1058 e
.getMessage().c_str());
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
1076 constexpr uint32_t kEvalVMInitialGlobalTableSizeDefault
= 512;
1077 constexpr uint64_t kJitRelocationSizeDefault
= 1 << 20;
1079 static const bool kJitTimerDefault
=
1080 #ifdef ENABLE_JIT_TIMER_DEFAULT
1088 #define F(type, name, def) \
1089 type RuntimeOption::Eval ## name = type(def);
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
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;
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;
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
;
1191 #ifdef ALWAYS_ASSERT
1192 const StaticString
s_hhvm_build_type("Release with asserts");
1194 const StaticString
s_hhvm_build_type("Release");
1197 const StaticString
s_hhvm_build_type("Debug");
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()) {
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
);
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
));
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());
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
1273 static std::vector
<std::string
> getTierOverwrites(IniSetting::Map
& ini
,
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");
1290 cpu
= Process::GetCPUModel();
1293 tiers
= Config::GetString(ini
, config
, "Machine.tiers");
1294 if (!tiers
.empty()) {
1295 if (!folly::readFile(tiers
.c_str(), tiers
)) {
1300 tags
= Config::GetString(ini
, config
, "Machine.tags");
1301 if (!tags
.empty()) {
1302 if (!folly::readFile(tags
.c_str(), tags
)) {
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.
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
;
1324 for (Hdf hdf
= config
["Tiers"].firstChild(); hdf
.exists();
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
) {
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();
1362 void RuntimeOption::ReadSatelliteInfo(
1363 const IniSettingMap
& ini
,
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
,
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
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.,
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
);
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 [{}] "
1452 folly::join(", ", original
),
1453 folly::join(", ", s_RelativeConfigs
)
1457 s_RelativeConfigs
.swap(newConfigs
);
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
;
1487 Config::Bind(ConfigId
, ini
, config
, "ConfigId", 0);
1488 auto configIdCounter
= ServiceData::createCounter("vm.config.id");
1489 configIdCounter
->setValue(ConfigId
);
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
;
1511 auto str
= Config::GetString(ini
, config
, "Log.Level");
1515 IniSetting::Bind(IniSetting::CORE
, IniSetting::PHP_INI_SYSTEM
,
1516 "hhvm.log.level", IniSetting::SetAndGet
<std::string
>(
1519 switch (Logger::LogLevel
) {
1520 case Logger::LogNone
:
1522 case Logger::LogError
:
1524 case Logger::LogWarning
:
1526 case Logger::LogInfo
:
1528 case Logger::LogVerbose
:
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",
1555 Config::Bind(Logger::AlwaysEscapeLog
, ini
, config
, "Log.AlwaysEscapeLog",
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",
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
,
1581 const std::string
&ini_pl_key
) {
1582 string logName
= hdf_pl
.exists() && !hdf_pl
.isEmpty()
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", "",
1589 string format
= Config::GetString(ini_pl
, hdf_pl
, "Format",
1590 AccessLogDefaultFormat
, false);
1591 auto periodMultiplier
= Config::GetUInt16(ini_pl
, hdf_pl
,
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",
1609 Config::Bind(AdminLogFile
, ini
, config
, "Log.AdminLog.File");
1610 Config::Bind(AdminLogSymLink
, ini
, config
, "Log.AdminLog.SymLink");
1615 Config::Bind(ErrorUpgradeLevel
, ini
, config
, "ErrorHandling.UpgradeLevel",
1617 Config::Bind(MaxSerializedStringSize
, ini
,
1618 config
, "ErrorHandling.MaxSerializedStringSize",
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");
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",
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
);
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",
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",
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";
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
;
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
);
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",
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",
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
);
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);
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",
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
1795 X(SerializeAndExit
);
1797 X(DeserializeOrFail
);
1798 X(DeserializeOrGenerate
);
1799 X(DeserializeAndDelete
);
1800 X(DeserializeAndExit
);
1802 return JitSerdesMode::Off
;
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);
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
) {
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(),
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 "
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",
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");
1939 using jit::CodeCache
;
1940 Config::Bind(CodeCache::AHotSize
, ini
, config
, "Eval.JitAHotSize",
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",
1947 Config::Bind(CodeCache::AFrozenSize
, ini
, config
, "Eval.JitAFrozenSize",
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);
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
1982 Config::Bind(AutoTypecheck
, ini
, config
, "Hack.Lang.AutoTypecheck",
1983 LookForTypechecker
);
1984 Config::Bind(EnableClassLevelWhereClauses
, ini
, config
,
1985 "Hack.Lang.EnableClassLevelWhereClauses",
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",
2005 Config::Bind(PHP7_NoHexNumerics
, ini
, config
, "PHP7.NoHexNumerics",
2007 Config::Bind(PHP7_Builtins
, ini
, config
, "PHP7.Builtins", s_PHP7_master
);
2008 Config::Bind(PHP7_Substr
, ini
, config
, "PHP7.Substr",
2010 Config::Bind(PHP7_DisallowUnsafeCurlUploads
, ini
, config
,
2011 "PHP7.DisallowUnsafeCurlUploads", s_PHP7_master
);
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");
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");
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",
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",
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",
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",
2119 Config::Bind(ServerKillOnTimeout
, ini
, config
, "Server.KillOnTimeout",
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",
2183 Config::Bind(ForceChunkedEncoding
, ini
, config
,
2184 "Server.ForceChunkedEncoding");
2185 Config::Bind(MaxPostSize
, ini
, config
, "Server.MaxPostSize", 100);
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",
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",
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",
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)
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);
2339 Config::Bind(UploadMaxFileSize
, ini
, config
,
2340 "Server.Upload.UploadMaxFileSize", 100);
2341 UploadMaxFileSize
<<= 20;
2342 Config::Bind(UploadTmpDir
, ini
, config
, "Server.Upload.UploadTmpDir",
2344 Config::Bind(EnableFileUploads
, ini
, config
,
2345 "Server.Upload.EnableFileUploads", true);
2346 Config::Bind(MaxFileUploads
, ini
, config
, "Server.Upload.MaxFileUploads",
2348 Config::Bind(EnableUploadProgress
, ini
, config
,
2349 "Server.Upload.EnableUploadProgress");
2350 Config::Bind(Rfc1867Freq
, ini
, config
, "Server.Upload.Rfc1867Freq",
2352 if (Rfc1867Freq
< 0) Rfc1867Freq
= 256 * 1024;
2353 Config::Bind(Rfc1867Prefix
, ini
, config
, "Server.Upload.Rfc1867Prefix",
2355 Config::Bind(Rfc1867Name
, ini
, config
, "Server.Upload.Rfc1867Name",
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
);
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();
2399 IpBlocks
= std::make_shared
<IpBlockMap
>(ini
, config
);
2402 ReadSatelliteInfo(ini
, config
, SatelliteServerInfos
,
2403 XboxPassword
, XboxPasswords
);
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",
2429 Config::Bind(XboxProcessMessageFunc
, ini
, config
, "Xbox.ProcessMessageFunc",
2430 "xbox_process_message");
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);
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",
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");
2472 Config::Bind(PhpFileExtensions
, ini
, config
, "PhpFile.Extensions");
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");
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");
2501 Config::Bind(HttpDefaultTimeout
, ini
, config
, "Http.DefaultTimeout", 30);
2502 Config::Bind(HttpSlowQueryThreshold
, ini
, config
, "Http.SlowQueryThreshold",
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",
2514 Config::Bind(ProfilerOutputDir
, ini
, config
, "Debug.ProfilerOutputDir",
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
);
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",
2556 Config::Bind(ProfilerTraceBuffer
, ini
, config
, "Stats.ProfilerTraceBuffer",
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");
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");
2589 Config::Bind(SendmailPath
, ini
, config
, "Mail.SendmailPath",
2590 "/usr/lib/sendmail -t -i");
2591 Config::Bind(MailForceExtraParameters
, ini
, config
,
2592 "Mail.ForceExtraParameters");
2596 Config::Bind(PregBacktraceLimit
, ini
, config
, "Preg.BacktraceLimit",
2598 Config::Bind(PregRecursionLimit
, ini
, config
, "Preg.RecursionLimit",
2600 Config::Bind(EnablePregErrorLog
, ini
, config
, "Preg.ErrorLog", true);
2604 Config::Bind(SimpleXMLEmptyNamespaceMatchesAll
, ini
, config
,
2605 "SimpleXML.EmptyNamespaceMatchesAll", false);
2610 Config::Bind(EnableFb303Server
, ini
, config
, "Fb303Server.Enable",
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",
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);
2630 Config::Bind(StrobelightEnabled
, ini
, config
, "Strobelight.Enabled", false);
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.)
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 // **************************************************************************
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
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",
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
);
2687 IniSetting::Bind(IniSetting::CORE
, IniSetting::PHP_INI_PERDIR
,
2689 IniSetting::SetAndGet
<int64_t>(
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
);
2707 IniSetting::Bind(IniSetting::CORE
, IniSetting::PHP_INI_ONLY
,
2708 "pid", &RuntimeOption::PidFile
);
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
);
2724 return convert_long_to_bytes(
2725 VirtualHost::GetUploadMaxFileSize());
2728 // Filesystem and Streams Configuration Options
2729 IniSetting::Bind(IniSetting::CORE
, IniSetting::PHP_INI_SYSTEM
,
2731 IniSetting::SetAndGet
<std::string
>(
2732 [](const std::string
& /*value*/) { return false; },
2733 []() { return "1"; }));
2736 IniSetting::Bind(IniSetting::CORE
, IniSetting::PHP_INI_NONE
,
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(); }));
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
,
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
,
2764 IniSetting::SetAndGet
<std::string
>(
2765 [](const std::string
&) {
2769 return s_hhvm_build_type
.c_str();
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
);
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);
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 ///////////////////////////////////////////////////////////////////////////////