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