]> granicus.if.org Git - icinga2/blob - lib/base/scriptframe.cpp
Merge pull request #7185 from Icinga/bugfix/gelfwriter-wrong-log-facility
[icinga2] / lib / base / scriptframe.cpp
1 /* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
2
3 #include "base/scriptframe.hpp"
4 #include "base/scriptglobal.hpp"
5 #include "base/namespace.hpp"
6 #include "base/exception.hpp"
7 #include "base/configuration.hpp"
8
9 using namespace icinga;
10
11 boost::thread_specific_ptr<std::stack<ScriptFrame *> > ScriptFrame::m_ScriptFrames;
12
13 static auto l_InternalNSBehavior = new ConstNamespaceBehavior();
14
15 /* Ensure that this gets called with highest priority
16  * and wins against other static initializers in lib/icinga, etc.
17  * LTO-enabled builds will cause trouble otherwise, see GH #6575.
18  */
19 INITIALIZE_ONCE_WITH_PRIORITY([]() {
20         Namespace::Ptr globalNS = ScriptGlobal::GetGlobals();
21
22         auto systemNSBehavior = new ConstNamespaceBehavior();
23         systemNSBehavior->Freeze();
24         Namespace::Ptr systemNS = new Namespace(systemNSBehavior);
25         globalNS->SetAttribute("System", std::make_shared<ConstEmbeddedNamespaceValue>(systemNS));
26
27         systemNS->SetAttribute("Configuration", std::make_shared<EmbeddedNamespaceValue>(new Configuration()));
28
29         auto typesNSBehavior = new ConstNamespaceBehavior();
30         typesNSBehavior->Freeze();
31         Namespace::Ptr typesNS = new Namespace(typesNSBehavior);
32         globalNS->SetAttribute("Types", std::make_shared<ConstEmbeddedNamespaceValue>(typesNS));
33
34         auto statsNSBehavior = new ConstNamespaceBehavior();
35         statsNSBehavior->Freeze();
36         Namespace::Ptr statsNS = new Namespace(statsNSBehavior);
37         globalNS->SetAttribute("StatsFunctions", std::make_shared<ConstEmbeddedNamespaceValue>(statsNS));
38
39         Namespace::Ptr internalNS = new Namespace(l_InternalNSBehavior);
40         globalNS->SetAttribute("Internal", std::make_shared<ConstEmbeddedNamespaceValue>(internalNS));
41 }, 1000);
42
43 INITIALIZE_ONCE_WITH_PRIORITY([]() {
44         l_InternalNSBehavior->Freeze();
45 }, 0);
46
47 ScriptFrame::ScriptFrame(bool allocLocals)
48         : Locals(allocLocals ? new Dictionary() : nullptr), Self(ScriptGlobal::GetGlobals()), Sandboxed(false), Depth(0)
49 {
50         InitializeFrame();
51 }
52
53 ScriptFrame::ScriptFrame(bool allocLocals, Value self)
54         : Locals(allocLocals ? new Dictionary() : nullptr), Self(std::move(self)), Sandboxed(false), Depth(0)
55 {
56         InitializeFrame();
57 }
58
59 void ScriptFrame::InitializeFrame()
60 {
61         std::stack<ScriptFrame *> *frames = m_ScriptFrames.get();
62
63         if (frames && !frames->empty()) {
64                 ScriptFrame *frame = frames->top();
65
66                 Sandboxed = frame->Sandboxed;
67         }
68
69         PushFrame(this);
70 }
71
72 ScriptFrame::~ScriptFrame()
73 {
74         ScriptFrame *frame = PopFrame();
75         ASSERT(frame == this);
76
77 #ifndef I2_DEBUG
78         (void)frame;
79 #endif /* I2_DEBUG */
80 }
81
82 void ScriptFrame::IncreaseStackDepth()
83 {
84         if (Depth + 1 > 300)
85                 BOOST_THROW_EXCEPTION(ScriptError("Stack overflow while evaluating expression: Recursion level too deep."));
86
87         Depth++;
88 }
89
90 void ScriptFrame::DecreaseStackDepth()
91 {
92         Depth--;
93 }
94
95 ScriptFrame *ScriptFrame::GetCurrentFrame()
96 {
97         std::stack<ScriptFrame *> *frames = m_ScriptFrames.get();
98
99         ASSERT(!frames->empty());
100         return frames->top();
101 }
102
103 ScriptFrame *ScriptFrame::PopFrame()
104 {
105         std::stack<ScriptFrame *> *frames = m_ScriptFrames.get();
106
107         ASSERT(!frames->empty());
108
109         ScriptFrame *frame = frames->top();
110         frames->pop();
111
112         return frame;
113 }
114
115 void ScriptFrame::PushFrame(ScriptFrame *frame)
116 {
117         std::stack<ScriptFrame *> *frames = m_ScriptFrames.get();
118
119         if (!frames) {
120                 frames = new std::stack<ScriptFrame *>();
121                 m_ScriptFrames.reset(frames);
122         }
123
124         if (!frames->empty()) {
125                 ScriptFrame *parent = frames->top();
126                 frame->Depth += parent->Depth;
127         }
128
129         frames->push(frame);
130 }