2015-05-12 30 views
7

Alcuni background: Sto cercando di rintracciare un bug che mi sta causando grossi grattacapi. Dopo molti vicoli ciechi (vedi this question) ho finalmente finito con questo codice:Il programma si blocca nel debugger di Visual Studio

#include <thread> 
#include <vector> 
#include <iosfwd> 
#include <sstream> 
#include <string> 
#include <windows.h> 

int main() 
{ 
    SRWLOCK srwl; 
    InitializeSRWLock(&srwl); 
    for(size_t i=0;i<1000;++i) 
    { 
     std::vector<std::thread>threads; 
     for(size_t j=0;j<100;++j) 
     { 
      OutputDebugString("."); 
      threads.emplace_back([&](){ 
       AcquireSRWLockExclusive(&srwl); 
       //Code below modifies the probability to see the bug. 
       std::this_thread::sleep_for(std::chrono::microseconds(1)); 
       std::wstringstream wss; 
       wss<<std::this_thread::get_id(); 
       wss.str(); 
       //Code above modifies the probability to see the bug. 
       ReleaseSRWLockExclusive(&srwl);}); 
     } 
     for(auto&t:threads){t.join();} 
     OutputDebugString((std::to_string(i)+"\n").data()); 
    } 
    return 0; 
} 

Quando ho eseguito questo codice all'interno di VS 2013 debugger il programma si blocca con una produzione come questa:

....................................................................................................0 
....................................................................................................1 
....................................................................................................2 
........................... 

Stranamente abbastanza, se metto in pausa il debugger e ispeziono cosa sta succedendo, uno dei thread è all'interno di AcquireSRWLockExclusive (in NtWaitForAlertByThreadId) apparentemente non c'è alcun motivo per cui il programma è in sospeso. Quando faccio clic su Riprendi, il programma continua felicemente e stampa un po 'di roba fino a quando non viene bloccato di nuovo.

Avete qualche idea cosa sta succedendo qui?

qualche informazione in più:

  • Per quanto posso dire, questo bug esiste solo su Windows 8.1.
  • Ho provato VS2013.4 e VS2015 RC.
  • Posso riprodurlo su due computer diversi in Windows 8.1.
  • Uno della macchina è stato formattato, la RAM, CPU e disco testati (ho pensato a un malfunzionamento, perché in un primo momento ho potuto osservare solo il bug su questa particolare macchina)
  • potrei mai riprodurlo su Windows 7.
  • Potrebbe essere utile modificare il codice tra i commenti per osservare il bug. Quando ho aggiunto il microsecondo, potrei finalmente riprodurre il bug su un altro computer.
  • Con VS2015 RC ho potuto riprodurre lo stesso comportamento con un semplice std :: mutex. Su VS2013 tuttavia SRWLOCK sembra obbligatorio per osservare il bug.
+0

Potrebbe essere in un deadlock e una volta inserito il debugger, la sincronizzazione cambia e il deadlock scompare. – NathanOliver

+0

@NathanOliver Come potrebbe essere possibile? C'è solo un mutex nel codice. – Arnaud

+0

Il programma si blocca quando viene eseguito all'esterno del debugger? –

risposta

4

Questo problema è causato da un bug dello scheduler del sistema operativo introdotto nell'aggiornamento della primavera 2014 a Windows 8.1. Una correzione per questo problema è stata rilasciata a maggio 2015 e disponibile a https://support.microsoft.com/en-us/kb/3036169.

+0

Ho provato l'aggiornamento rapido e risolve il problema. Tuttavia sembra molto più lento. – Arnaud

1

Per me sembra un bug in Windows OS, ho diverse varianti di codice che si blocca utilizzando nuove primitive di Vista in debugger in Win 8.1/Server 2012R2 dopo l'aggiornamento di aprile 2014. Anche la funzione di attesa del pool di thread si blocca. Sembra che sia per lo più legato ad altri thread finiti di esecuzione al momento dell'attesa/blocco. Ecco il codice semplice che pende sempre sotto debugger in NtWaitForAlertByThreadId():

#include <windows.h> 

#include <stdio.h> 
#include <conio.h> 
#include <tchar.h> 

#pragma optimize("",off) 
VOID CALLBACK _WorkCallback(PTP_CALLBACK_INSTANCE Instance, PVOID pUser, PTP_WORK Work) 
{ 
    for (int i = 0; i < INT_MAX/256; i++) {} 
} 

DWORD WINAPI ThreadProc(LPVOID lpParameter) 
{ 
    for (int i = 0; i < INT_MAX/256; i++) {} 
    return 0; 
} 
#pragma optimize("",on) 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    LONGLONG c = 0; 

    while(!_kbhit()) 
    { 
     PTP_WORK ptpw = CreateThreadpoolWork(&_WorkCallback, NULL, NULL); 
     if (ptpw != NULL) 
     { 
      for(long i = 0; i < 3; i++) SubmitThreadpoolWork(ptpw); 

      CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL); 

      WaitForThreadpoolWorkCallbacks(ptpw, FALSE); 
      CloseThreadpoolWork(ptpw); 
     } 

     printf("%I64d         \r", c++); 
    } 

    _getch(); 
    return 0; 
} 

Purtroppo non ho idea di dove segnalarlo alla Microsoft.

+0

Posso anche riprodurre l'impiccagione sul mio sistema. – Arnaud

Problemi correlati