comparison Framework/Oracle/WebAssemblyOracle.cpp @ 973:38409549db43 toa2019082903

Log with addresses + added fingerprint mechanism to avoid calling zombie objects where: - a message is sent with a receiver - the receiver dies - another receiver with the SAME address is created - the message reply is executed --> execution on the wrong object! (since their "identity" is their address. The fix is to identify them with an UUID stored at creation time)
author Benjamin Golinvaux <bgo@osimis.io>
date Thu, 29 Aug 2019 18:07:55 +0200
parents bc7b249dfbd0
children e75fd08d6c75
comparison
equal deleted inserted replaced
972:fdf8b013f228 973:38409549db43
97 class WebAssemblyOracle::FetchContext : public boost::noncopyable 97 class WebAssemblyOracle::FetchContext : public boost::noncopyable
98 { 98 {
99 private: 99 private:
100 Emitter emitter_; 100 Emitter emitter_;
101 const IObserver& receiver_; 101 const IObserver& receiver_;
102 std::string receiverFingerprint_;
102 std::auto_ptr<IOracleCommand> command_; 103 std::auto_ptr<IOracleCommand> command_;
103 std::string expectedContentType_; 104 std::string expectedContentType_;
104 105
105 public: 106 public:
106 FetchContext(WebAssemblyOracle& oracle, 107 FetchContext(WebAssemblyOracle& oracle,
107 const IObserver& receiver, 108 const IObserver& receiver,
108 IOracleCommand* command, 109 IOracleCommand* command,
109 const std::string& expectedContentType) : 110 const std::string& expectedContentType) :
110 emitter_(oracle), 111 emitter_(oracle),
111 receiver_(receiver), 112 receiver_(receiver),
113 receiverFingerprint_(receiver.GetFingerprint()),
112 command_(command), 114 command_(command),
113 expectedContentType_(expectedContentType) 115 expectedContentType_(expectedContentType)
114 { 116 {
115 if (command == NULL) 117 if (command == NULL)
116 { 118 {
117 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); 119 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer);
118 } 120 }
121 }
122
123 bool IsFingerprintOK() const
124 {
125 bool ok = receiverFingerprint_ == receiver_.GetFingerprint();
126 if (!ok)
127 {
128 LOG(TRACE) << "IsFingerprintOK returned false. receiverFingerprint_ = " << receiverFingerprint_ << " | receiver_(" << std::hex << (&receiver_) << std::dec << ").GetFingerprint() = " << receiver_.GetFingerprint();
129 }
130 return ok;
119 } 131 }
120 132
121 const std::string& GetExpectedContentType() const 133 const std::string& GetExpectedContentType() const
122 { 134 {
123 return expectedContentType_; 135 return expectedContentType_;
193 * Firstly, make a local copy of the fetched information, and 205 * Firstly, make a local copy of the fetched information, and
194 * free data associated with the fetch. 206 * free data associated with the fetch.
195 **/ 207 **/
196 208
197 std::auto_ptr<FetchContext> context(reinterpret_cast<FetchContext*>(fetch->userData)); 209 std::auto_ptr<FetchContext> context(reinterpret_cast<FetchContext*>(fetch->userData));
210
198 if (fetch->userData == NULL) 211 if (fetch->userData == NULL)
199 { 212 {
200 LOG(ERROR) << "WebAssemblyOracle::FetchContext::SuccessCallback fetch->userData is NULL!!!!!!!"; 213 LOG(ERROR) << "WebAssemblyOracle::FetchContext::SuccessCallback fetch->userData is NULL!!!!!!!";
201 } 214 }
202 215
232 #endif 245 #endif
233 emscripten_fetch_close(fetch); 246 emscripten_fetch_close(fetch);
234 247
235 /** 248 /**
236 * Secondly, use the retrieved data. 249 * Secondly, use the retrieved data.
250 * We only use the receiver if its fingerprint matches the one stored
251 * at command creation.
237 **/ 252 **/
238 253 if (!context->IsFingerprintOK())
239 try 254 {
240 { 255 LOG(WARNING) << "FetchContext::SuccessCallback -- the initial request initiator has been destroyed. Response will be discarded.";
241 if (context.get() == NULL) 256 }
257 else
258 {
259 try
242 { 260 {
243 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); 261 if (context.get() == NULL)
244 }
245 else
246 {
247 switch (context->GetCommand().GetType())
248 { 262 {
263 throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer);
264 }
265 else
266 {
267 switch (context->GetCommand().GetType())
268 {
249 case IOracleCommand::Type_OrthancRestApi: 269 case IOracleCommand::Type_OrthancRestApi:
250 { 270 {
251 OrthancRestApiCommand::SuccessMessage message 271 OrthancRestApiCommand::SuccessMessage message
252 (context->GetTypedCommand<OrthancRestApiCommand>(), headers, answer); 272 (context->GetTypedCommand<OrthancRestApiCommand>(), headers, answer);
253 context->EmitMessage(message); 273 context->EmitMessage(message);
254 break; 274 break;
255 } 275 }
256 276
257 case IOracleCommand::Type_GetOrthancImage: 277 case IOracleCommand::Type_GetOrthancImage:
258 { 278 {
259 context->GetTypedCommand<GetOrthancImageCommand>().ProcessHttpAnswer 279 context->GetTypedCommand<GetOrthancImageCommand>().ProcessHttpAnswer
260 (context->GetEmitter(), context->GetReceiver(), answer, headers); 280 (context->GetEmitter(), context->GetReceiver(), answer, headers);
261 break; 281 break;
262 } 282 }
263 283
264 case IOracleCommand::Type_GetOrthancWebViewerJpeg: 284 case IOracleCommand::Type_GetOrthancWebViewerJpeg:
265 { 285 {
266 context->GetTypedCommand<GetOrthancWebViewerJpegCommand>().ProcessHttpAnswer 286 context->GetTypedCommand<GetOrthancWebViewerJpegCommand>().ProcessHttpAnswer
267 (context->GetEmitter(), context->GetReceiver(), answer); 287 (context->GetEmitter(), context->GetReceiver(), answer);
268 break; 288 break;
269 } 289 }
270 290
271 default: 291 default:
272 LOG(ERROR) << "Command type not implemented by the WebAssembly Oracle: " 292 LOG(ERROR) << "Command type not implemented by the WebAssembly Oracle: "
273 << context->GetCommand().GetType(); 293 << context->GetCommand().GetType();
294 }
274 } 295 }
275 } 296 }
276 } 297 catch (Orthanc::OrthancException& e)
277 catch (Orthanc::OrthancException& e) 298 {
278 { 299 LOG(ERROR) << "Error while processing a fetch answer in the oracle: " << e.What();
279 LOG(ERROR) << "Error while processing a fetch answer in the oracle: " << e.What(); 300 }
280 } 301 }
281 } 302 }
282 303
283 static void FailureCallback(emscripten_fetch_t *fetch) 304 static void FailureCallback(emscripten_fetch_t *fetch)
284 { 305 {