Jump to content











Photo
- - - - -

Tftpd32 spins at REALTIME_PRIORITY on some unhandled errors

tfpd32

  • Please log in to reply
No replies to this topic

#1 AHenry

AHenry
  • Members
  • 3 posts
  •  
    United States

Posted 31 August 2015 - 03:15 PM

We ran into this while chasing an interface binding error (for some reason tftpd32 is starting the tftp server thread when the interface is unavailable on our Windows 7 boxes).  When we started the tftpd32 service with the network jack disconnected, the service would use up a full core's CPU at real time priority, making the keyboard very slow to respond among other problems.  On a single core cpu, this could really be bad.  It turns out that the "scheduler" thread would continuously loop if a thread it was monitoring ended unexpectedly.
 
I ended up putting several patches into the scheduler thread while I was tracking this down, adding some error handling on the thread monitoring, reducing the thread priority from real time, and possibly fixing a gui update bug.
 
in start_threads.c:

void Scheduler (void *param)
{
unsigned int Ark;
unsigned int Rc;
int waitIndex;
HANDLE tHdle[TH_NUMBER];
unsigned int nCount;
int  nTime=1000;

	// Increase thread priority in order to return asap in the Wait function
     SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);

    tThreads [TH_SCHEDULER].bInit = TRUE;  // inits OK

    do
	{
		tHdle[0] = tThreads [TH_SCHEDULER].hEv;
        for ( Ark=0, nCount=1 ;  Ark<TH_NUMBER ; Ark++ )
             if (tThreads [Ark].gRunning)     tHdle[nCount++] = tThreads [Ark].tTh;
		// wake up every 30 seconds
		waitIndex = -1;
        Rc = WaitForMultipleObjects (nCount, tHdle, FALSE, 30000);
		if (Rc == WAIT_TIMEOUT)  
			PoolNetworkInterfaces ();	// so not trigger messages to GUI
		else if (Rc == WAIT_FAILED)  
			LogToMonitor ("Scheduler wait returns %d (error %d - %s)\n", Rc, GetLastError (), LastErrorText());
		else if ( Rc - WAIT_OBJECT_0 < nCount && Rc - WAIT_OBJECT_0 >= 0 )
			waitIndex = Rc - WAIT_OBJECT_0;
		else
			LogToMonitor ("Scheduler wait returns invalid index %d\n", Rc);


		// a process has terminated 
		if ( waitIndex >= 0  )
		{
		struct S_Chg_Service chgmsg;

			 // thread itself is signalled, since the number of service has changed
			 if (waitIndex == 0)
			 { 
				LogToMonitor ("Scheduler signal received"); 
				ResetEvent (tThreads[TH_SCHEDULER].hEv); // was tThreads[Ark].hEv; this should work better
				PoolNetworkInterfaces ();	// GUI has waked up this thread, send it fresh info
				continue; 
			 }

			for ( Ark=0 ;  Ark<SizeOfTab(tThreads)  &&  tHdle[waitIndex]!=tThreads [Ark].tTh ;  Ark++ ); 
			if (Ark>=SizeOfTab(tThreads)) continue;

			LogToMonitor ("process %s has terminated\n", tThreadsConfig[Ark].name);


			// free resources allocated by StartSingleWorkerThread
			FreeThreadResources (Ark);
     		if (tThreadsConfig [Ark].gui)
 			{
				// change display : ie add its tab in the GUI
				chgmsg.service = tThreadsConfig [Ark].serv_mask;
				chgmsg.status = SERVICE_STOPPED;
   				SendMsgRequest (C_CHG_SERVICE,& chgmsg, sizeof chgmsg, FALSE, FALSE );	
			}

			// wait since uServices may be changed by Console thread !!
			if (    tThreadsConfig [Ark].restart 
				&&  sSettings.uServices & tThreadsConfig [Ark].serv_mask 
				&&  tThreads [Ark].gRunning )
				StartSingleWorkerThread (Ark);
			else
				tThreads[Ark].gRunning = FALSE;

		} // WAitMultipleObject
		else
			Sleep(1000);
    }
    while ( tThreads[TH_SCHEDULER].gRunning );

	LogToMonitor ("end of ip pooling thread\n");
_endthread ();        
} // ListIPInterfaces






0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users