JIT: Fix bug in finally cloning caused by unsound callfinally reordering
[platform/upstream/coreclr.git] / src / zap / svcworker.cpp
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4
5
6 /**********************************************************************
7 svcworker.cpp -- logic for the runtime implementation of the native 
8 image service.
9
10 Overview:  the runtime implementation is accessed via a local COM
11 server implemented in ngen.exe.  That server is simply a stub that
12 loads the most recent runtime and calls into the actual implementation
13 in this file.  There are three entrypoints in mscorwks.dll that
14 are called by the local service in ngen.exe:
15
16 NGenWorkerRegisterServer -- called to register ngen.exe as the current
17   COM server for CLSID_CorSvcWorker
18 NGenWorkerUnregisterServer -- unregister ngen.exe as the current COM
19   server for CLSID_CorSvcWorker
20 NGenWorkerEmbedding() -- called when COM invoked the COM server with
21   the "-Embedding" flag.  Implements the logic for registering the class
22   factory for CLSID_CorSvcWorker and controlling the lifetime of the
23   COM server.
24 **********************************************************************/
25
26 #include "common.h"
27
28
29 #ifdef FEATURE_APPX
30 #include "AppXUtil.h"
31 #endif
32
33 ILocalServerLifetime *g_pLocalServerLifetime = NULL;
34
35 SvcLogger::SvcLogger()
36     : pss(NULL),
37       pCorSvcLogger(NULL)
38 {
39 }
40
41 inline void SvcLogger::CheckInit()
42 {
43     if(pss == NULL)
44     {
45         StackSString* psstemp = new StackSString();
46         StackSString* pssOrig = InterlockedCompareExchangeT(&pss, psstemp, NULL); 
47         if(pssOrig)
48             delete psstemp;  
49     }        
50 }
51
52 SvcLogger::~SvcLogger()
53 {
54     if (pCorSvcLogger)
55     {
56 //        pCorSvcLogger->Release();
57         pCorSvcLogger = NULL;
58     }
59     if (pss)
60         delete pss;
61 }
62
63 void SvcLogger::ReleaseLogger()
64 {
65     if (pCorSvcLogger)
66     {
67         pCorSvcLogger->Release();
68         pCorSvcLogger = NULL;
69     }
70 }
71
72 void SvcLogger::Printf(const CHAR *format, ...)
73 {
74     StackSString s;
75
76     va_list args;
77     va_start(args, format);
78     s.VPrintf(format, args);
79     va_end(args);
80
81     if (pCorSvcLogger)
82     {
83         LogHelper(s);
84     }
85     else
86     {
87         wprintf( W("%s"), s.GetUnicode() );
88     }
89 }
90
91 void SvcLogger::SvcPrintf(const CHAR *format, ...)
92 {
93     StackSString s;
94
95     va_list args;
96     va_start(args, format);
97     s.VPrintf(format, args);
98     va_end(args);
99
100     LogHelper(s);
101 }
102
103 void SvcLogger::Printf(const WCHAR *format, ...)
104 {
105     StackSString s;
106
107     va_list args;
108     va_start(args, format);
109     s.VPrintf(format, args);
110     va_end(args);
111
112     if (pCorSvcLogger)
113     {
114         LogHelper(s);
115     }
116     else
117     {
118         wprintf( W("%s"), s.GetUnicode() );
119     }
120 }
121
122 void SvcLogger::Printf(CorSvcLogLevel logLevel, const WCHAR *format, ...)
123 {
124     StackSString s;
125
126     va_list args;
127     va_start(args, format);
128     s.VPrintf(format, args);
129     va_end(args);
130
131     if (pCorSvcLogger)
132     {
133         LogHelper(s, logLevel);
134     }
135     else
136     {
137         wprintf( W("%s"), s.GetUnicode());
138     }
139 }
140
141 void SvcLogger::SvcPrintf(const WCHAR *format, ...)
142 {
143     StackSString s;
144
145     va_list args;
146     va_start(args, format);
147     s.VPrintf(format, args);
148     va_end(args);
149
150     LogHelper(s);
151 }
152
153 void SvcLogger::Log(const WCHAR *message, CorSvcLogLevel logLevel)
154 {
155     LogHelper(StackSString(message), logLevel);
156 }
157
158 void SvcLogger::LogHelper(SString s, CorSvcLogLevel logLevel)
159 {
160     CheckInit(); 
161     pss->Append(s);
162
163     // Does s contain a newline?
164     SString::Iterator i = pss->Begin();
165     if (pss->FindASCII(i, "\n"))
166     {
167         if (pCorSvcLogger)
168         {
169             BSTRHolder bstrHolder(::SysAllocString(pss->GetUnicode()));
170             // Can't use the IfFailThrow macro here because in checked
171             // builds that macros will try to log an error message
172             // that will recursively return to this method.
173             HRESULT hr = pCorSvcLogger->Log(logLevel, bstrHolder);
174             if (FAILED(hr))
175                 ThrowHR(hr);
176         }
177         pss->Clear();
178     }
179 }
180
181 void SvcLogger::SetSvcLogger(ICorSvcLogger *pCorSvcLoggerArg)
182 {
183     ReleaseLogger();
184     this->pCorSvcLogger = pCorSvcLoggerArg;
185     if (pCorSvcLoggerArg)
186     {
187         pCorSvcLogger->AddRef();
188     }
189 }
190
191 BOOL SvcLogger::HasSvcLogger()
192 {
193     return (this->pCorSvcLogger != NULL);
194 }
195
196 ICorSvcLogger* SvcLogger::GetSvcLogger()
197 {
198     return pCorSvcLogger;
199 }
200
201
202 namespace
203 {
204     SvcLogger *g_SvcLogger = NULL;
205 }
206
207 // As NGen is currently single-threaded, this function is intentionally not thread safe.
208 // If necessary, change it into an interlocked function.
209 SvcLogger *GetSvcLogger()
210 {
211     if (g_SvcLogger == NULL)
212     {
213         g_SvcLogger = new SvcLogger();
214     }
215     return g_SvcLogger;
216 }
217
218 BOOL HasSvcLogger()
219 {
220     if (g_SvcLogger != NULL)
221     {
222         return g_SvcLogger->HasSvcLogger();
223     }
224     return FALSE;
225 }
226
227 #ifdef CROSSGEN_COMPILE
228 void SetSvcLogger(ICorSvcLogger *pCorSvcLogger)
229 {
230     GetSvcLogger()->SetSvcLogger(pCorSvcLogger);
231 }
232 #endif
233