@@ -225,10 +225,8 @@ void NativeJSRenderer::setEnvForConsoleMode(ModuleSettings& moduleSettings)
225225
226226uint32_t NativeJSRenderer::createApplicationIdentifier ()
227227{
228- static uint32_t id = 1 ;
229- uint32_t ret = id;
230- id++;
231- return ret;
228+ static std::atomic<uint32_t > id{1 };
229+ return id++;
232230}
233231
234232uint32_t NativeJSRenderer::createApplication (ModuleSettings& moduleSettings, std::string userAgent)
@@ -292,6 +290,7 @@ bool NativeJSRenderer::terminateApplication(uint32_t id)
292290 return true ;
293291}
294292
293+ // REQUIRES: Caller must hold mUserMutex
295294void NativeJSRenderer::createApplicationInternal (ApplicationRequest& appRequest)
296295{
297296 double startTime = getTimeInMilliSec ();
@@ -330,9 +329,9 @@ void NativeJSRenderer::createApplicationInternal(ApplicationRequest& appRequest)
330329 context->setCreateApplicationEndTime (endTime, id);
331330
332331 mContextMap [id].context =context;
333- mUserMutex .unlock ();
334332}
335333
334+ // REQUIRES: Caller must hold mUserMutex
336335void NativeJSRenderer::runApplicationInternal (ApplicationRequest& appRequest)
337336{
338337 uint32_t id = appRequest.mId ;
@@ -365,7 +364,7 @@ void NativeJSRenderer::runApplicationInternal(ApplicationRequest& appRequest)
365364 NativeJSLogger::log (INFO, " Adding the window location: %s to js file\n " , window.str ().c_str ());
366365 context->runScript (window.str ().c_str (),true , url, nullptr , true );
367366 }
368- NativeJSLogger::log (INFO, " nativeJS application thunder execution url: %s, result: %d \n " , url.c_str (), ret ? 1 : 0 );
367+ NativeJSLogger::log (INFO, " nativeJS application thunder execution url: %s\n " , url.c_str ());
369368 ret = context->runScript (chunk.contentsBuffer , true , url, nullptr , true );
370369 NativeJSLogger::log (INFO, " nativeJS application execution result: %d\n " , ret ? 1 : 0 );
371370 double duration = context->getExecutionDuration ();
@@ -398,6 +397,7 @@ void NativeJSRenderer::runApplicationInternal(ApplicationRequest& appRequest)
398397 }
399398}
400399
400+ // REQUIRES: Caller must hold mUserMutex
401401void NativeJSRenderer::runJavaScriptInternal (ApplicationRequest& appRequest)
402402{
403403 uint32_t id = appRequest.mId ;
@@ -427,6 +427,7 @@ void NativeJSRenderer::runJavaScriptInternal(ApplicationRequest& appRequest)
427427 }
428428}
429429
430+ // REQUIRES: Caller must hold mUserMutex
430431void NativeJSRenderer::terminateApplicationInternal (ApplicationRequest& AppRequest)
431432{
432433 uint32_t id = AppRequest.mId ;
@@ -445,7 +446,7 @@ void NativeJSRenderer::terminateApplicationInternal(ApplicationRequest& AppReque
445446
446447 else
447448 {
448- NativeJSLogger::log (ERROR, " Unable to find application with id: %d and url: %s \n " , id, mContextMap [id]. url );
449+ NativeJSLogger::log (ERROR, " Unable to find application with id: %d\n " , id);
449450 return ;
450451 }
451452
@@ -468,11 +469,10 @@ void NativeJSRenderer::run()
468469{
469470 while (mRunning )
470471 {
471- uint32_t id;
472- mUserMutex .lock ();
473472 if (mConsoleMode ) {
474473 processDevConsoleRequests ();
475474 }
475+ mUserMutex .lock ();
476476 for (int i=0 ; i<gPendingRequests .size (); i++)
477477 {
478478
@@ -506,10 +506,13 @@ void NativeJSRenderer::run()
506506 if (!mTestFileName .empty ())
507507 {
508508 ModuleSettings settings;
509+ uint32_t id = createApplicationIdentifier ();
509510 settings.enableJSDOM = mEnableTestFileDOMSupport ;
510511 ApplicationRequest appRequest (id, RUN, mTestFileName , settings.enableHttp , settings.enableXHR , settings.enableWebSocket , settings.enableWebSocketEnhanced , settings.enableFetch , settings.enableJSDOM , settings.enableWindow , settings.enablePlayer );
512+ mUserMutex .lock ();
511513 NativeJSRenderer::createApplicationInternal (appRequest);
512514 NativeJSRenderer::runApplicationInternal (appRequest);
515+ mUserMutex .unlock ();
513516 mTestFileName = " " ;
514517 }
515518
@@ -531,27 +534,30 @@ void NativeJSRenderer::run()
531534
532535void NativeJSRenderer::processDevConsoleRequests ()
533536{
537+ std::deque<std::string> localQueue;
538+
539+ // Move items from shared queue to local queue while holding the lock
534540 mConsoleState ->inputMutex .lock ();
535-
536541 if (mConsoleState ->codeToExecute .empty ()) {
537542 mConsoleState ->inputMutex .unlock ();
538543 return ;
539544 }
545+ localQueue.swap (mConsoleState ->codeToExecute );
546+ mConsoleState ->inputMutex .unlock ();
540547
541548 std::lock_guard<std::mutex> lockg (mConsoleState ->isProcessing_cv_m );
542549 bool dataProcessed = false ;
543550
544- for (; !mConsoleState ->codeToExecute .empty (); mConsoleState ->codeToExecute .pop_front ()) {
545- bool ret = mConsoleState ->consoleContext ->runScript (mConsoleState ->codeToExecute .front ().c_str (), false );
551+ // Process items from local queue (no race condition)
552+ for (const auto & code : localQueue) {
553+ bool ret = mConsoleState ->consoleContext ->runScript (code.c_str (), false );
546554 dataProcessed = true ;
547555 }
548556
549557 if (dataProcessed) {
550558 mConsoleState ->isProcessing = false ;
551559 mConsoleState ->isProcessing_cv .notify_one ();
552560 }
553-
554- mConsoleState ->inputMutex .unlock ();
555561}
556562
557563std::atomic_bool NativeJSRenderer::consoleLoop = true ;
@@ -620,18 +626,34 @@ bool NativeJSRenderer::downloadFile(std::string& url, MemoryStruct& chunk)
620626 curl = curl_easy_init ();
621627 if (curl)
622628 {
623- curl_easy_setopt (curl, CURLOPT_URL, url.c_str ());
624- curl_easy_setopt (curl, CURLOPT_FOLLOWLOCATION, 1 );
625- curl_easy_setopt (curl, CURLOPT_HEADERFUNCTION, HeaderCallback);
626- curl_easy_setopt (curl, CURLOPT_HEADERDATA, (void *)&chunk);
627- curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
628- curl_easy_setopt (curl, CURLOPT_WRITEDATA, (void *)&chunk);
629- curl_easy_setopt (curl, CURLOPT_TIMEOUT, 30 );
630- curl_easy_setopt (curl, CURLOPT_NOSIGNAL, 1L );
631- curl_easy_setopt (curl, CURLOPT_SSL_VERIFYHOST, 2 );
632- curl_easy_setopt (curl, CURLOPT_SSL_VERIFYPEER, true );
633- curl_easy_setopt (curl, CURLOPT_USERAGENT, " libcurl-agent/1.0" );
634- curl_easy_setopt (curl, CURLOPT_PROXY, " " );
629+ // Helper lambda to check curl_easy_setopt results
630+ auto setOptWithCheck = [curl](CURLoption option, auto value, const char * optionName) -> bool {
631+ CURLcode optRes = curl_easy_setopt (curl, option, value);
632+ if (optRes != CURLE_OK) {
633+ NativeJSLogger::log (ERROR, " Failed to set %s: %s\n " , optionName, curl_easy_strerror (optRes));
634+ return false ;
635+ }
636+ return true ;
637+ };
638+
639+ // Set options; cleanup and return if any fail
640+ if (
641+ !setOptWithCheck (CURLOPT_URL, url.c_str (), " CURLOPT_URL" ) ||
642+ !setOptWithCheck (CURLOPT_FOLLOWLOCATION, 1L , " CURLOPT_FOLLOWLOCATION" ) ||
643+ !setOptWithCheck (CURLOPT_HEADERFUNCTION, HeaderCallback, " CURLOPT_HEADERFUNCTION" ) ||
644+ !setOptWithCheck (CURLOPT_HEADERDATA, (void *)&chunk, " CURLOPT_HEADERDATA" ) ||
645+ !setOptWithCheck (CURLOPT_WRITEFUNCTION, WriteMemoryCallback, " CURLOPT_WRITEFUNCTION" ) ||
646+ !setOptWithCheck (CURLOPT_WRITEDATA, (void *)&chunk, " CURLOPT_WRITEDATA" ) ||
647+ !setOptWithCheck (CURLOPT_TIMEOUT, 30L , " CURLOPT_TIMEOUT" ) ||
648+ !setOptWithCheck (CURLOPT_NOSIGNAL, 1L , " CURLOPT_NOSIGNAL" ) ||
649+ !setOptWithCheck (CURLOPT_SSL_VERIFYHOST, 2L , " CURLOPT_SSL_VERIFYHOST" ) ||
650+ !setOptWithCheck (CURLOPT_SSL_VERIFYPEER, 1L , " CURLOPT_SSL_VERIFYPEER" ) ||
651+ !setOptWithCheck (CURLOPT_USERAGENT, " libcurl-agent/1.0" , " CURLOPT_USERAGENT" ) ||
652+ !setOptWithCheck (CURLOPT_PROXY, " " , " CURLOPT_PROXY" )
653+ ) {
654+ curl_easy_cleanup (curl);
655+ return ret;
656+ }
635657
636658
637659 // curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
0 commit comments