Pergunta

Eu estou tendo uma situação sem saída com um dos clientes usando o meu software. Fora de cerca de 40 cópias do nosso produto vendido (Aplicação programados em .NET 2.0 usando VB.NET 2005), cerca de 2 obter não-responsivo com um núcleo dos processadores de núcleo duplo preso a 100% (programa usa um núcleo apenas)

A suposição mais lógica é um loop infinito causando esse comportamento, mas a milhares de linhas de código com muitos, muitos loops. Essa é toda a informação que eu tenho; Agora, como você sugere que eu abordagem depuração este problema?

EDIT: Basicamente, o software é responsável pelo cálculo montante de crédito gasto com outros dispositivos, como PCs, etc. É um programa de gestão Cybercafe e falha intermitente ou seja, ele está subtraindo crédito quando é falha. Ele faz outras coisas no fundo também, como a verificação para ver se é hora de criar um backup de banco de dados, entre outras coisas.

EDIT: Resolvido. Ele foi o problema mais improvável. O motor de banco de dados Access que eu usei como o DBMS é realmente a parte do meu aplicativo que é problemático. Ele tem dificuldade em trabalhar com uma linha-APENAS UMA FRIGGIN ROW-in de uma das mesas. Eu não posso excluí-lo, ou não adicionar um registro relacionado a essa linha em qualquer outra tabela; Mesmo MS Access 2007 faz com que a CPU para ir até 100% quando eu tento trabalhar com essa linha!

Um simples "Compact e Reparação" comando tudo fixo. Acho que vou emitir esse comando cada vez que meu aplicativo é iniciado. Isso iria evitar que isso aconteça novamente.

Graças ao WinDbg eu poderia encontrar onde o problema era. Eu recomendo a todos a aprender a usá-lo porque é uma proteção em tempo real.

Foi útil?

Solução

Instale windbg (depurador Windows) na máquina de destino. Invocar o depurador, e anexar ao processo suspeito, execute o programa e aguarde até que o problema acontece. Quando o problema acontece, invoque o seguinte comando na linha de comando depurador

! Fugitivo

Isto irá mostrar quais dos seus tópicos estão consumindo a maior parte do tempo. Em seguida, obter várias pilhas de rosca de que thread que está consumindo a maior parte de seus recursos de CPU.

Aqui está um exemplo:

0:015> !runaway

User Time Modo Passe Tempo 0: 1074 0 dia 0: 00: 21.637 11: 137c 0 dias 0: 00: 02.792 4: 12c8 0 dias 0: 00: 00.530 9: 1374 0 dia 0: 00: 00.046 15: 13d0 0 dias 0: 00: 00.000 14: 1204 0 dia 0: 00: 00.000 13: 154C 0 dias 0: 00: 00.000 12: 144c 0 dias 0: 00: 00.000 10: 1378 0 dia 0: 00: 00.000 8: 1340 0 dia 0: 00: 00.000 7: 12f0 0 dias 0: 00: 00.000 6: 12d4 0 dia 0: 00: 00.000 5: 12d0 0 dias 0: 00: 00.000 3: 12c4 0 dias 0: 00: 00.000 2: 12c0 0 dias 0: 00: 00.000 1: 12B4 0 dias 0: 00: 00.000

Agora vamos supor que queremos uma pilha de chamadas para o segundo segmento na lista, passe 11, de modo que primeiro switch para passar a linha 11. Isso pode ser feito inserindo ~ 11s.

0:015> ~11s

eax = 03fbb270 EBX = ffffffff ECX = 00000002 edx = 00000060 ESI = 00000000 edi = 00000000 EIP = 77475e74 esp = 0572f60c ebp = 0572f67c IOPL = 0 nv-se ei pl zr na pe nc cs = 001b ss = 0023 = 0023 ds es = 0.023 fs = 003b GS = 0,000 efl = 00000246 ! Ntdll KiFastSystemCallRet: 77475e74 c3 ret

Agora pegue uma pilha de chamadas para esta discussão, executando KP:

0:011> kp
ChildEBP RetAddr  
0572f608 77475620 ntdll!KiFastSystemCallRet
0572f60c 75b09884 ntdll!NtWaitForSingleObject+0xc
0572f67c 75b097f2 kernel32!WaitForSingleObjectEx+0xbe
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\Program Files\Mozilla Firefox 3.1 Beta 1\nspr4.dll - 
0572f690 10019a0b kernel32!WaitForSingleObject+0x12
WARNING: Stack unwind information not available. Following frames may be wrong.
0572f6ac 10015979 nspr4!PR_MD_WAIT_CV+0x8b
0572f6c4 10015763 nspr4!PR_GetPrimordialCPU+0x79
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\Program Files\Mozilla Firefox 3.1 Beta 1\xul.dll - 
0572f6e0 64d44d6a nspr4!PR_Wait+0x33
0572f708 64dbe67e xul!NS_CycleCollectorForget2_P+0x698a
0572f72c 10019b3f xul!gfxWindowsPlatform::FontEnumProc+0xfd4e
0572f734 10015d32 nspr4!PR_MD_UNLOCK+0x1f
0572f738 1001624b nspr4!PR_Unlock+0x22
0572f754 1001838d nspr4!PRP_TryLock+0x4cb
00000000 00000000 nspr4!PR_Now+0x109d

O KP comando irá imprimir os parâmetros. As variáveis ??locais podem ser impressas com dv.

Como alternativa, você pode usar o Process Explorer da Sysinternals.

Se tudo isso não é possível, porque é uma máquina cliente remota, instale userdump, o que cria um arquivo de despejo, que pode ser enviado a você para análise posterior. Você pode criar um arquivo de lote para o cliente para invocar userdump com os parâmetros corretos. Userdump é uma ferramenta da Microsoft, que pode ser baixado a partir de sua página web.

Outras dicas

Se possível, obter um despejo de processo e olhar para o rastreamento de pilha.
Eu nunca fiz isso, mas ele deve funcionar com VS / WinDbg e SOS (Filho de greve). Aqui é um Blog Post sobre isso.

Se é um loop infinito, em seguida, tentar anexar um depurador e bater pausa. WinDbg é ideal para isso.

A técnica também funciona para o caso quando o circuito está apenas repetindo muitas vezes, mas, eventualmente, continua com o resto do código. É possível passar um par de minutos, repetindo o procedimento para obter uma amostra de bom.

Esta técnica tem me salvou várias vezes e funciona bem para aplicações penduradas também:)

Bem, você vai precisar trabalhar para fora onde é tight-looping. Qual é o seu cliente fazendo com o software no momento? O que faz o software que, em primeiro lugar?

Você pode querer considerar a adição de um monte de registro para o seu código e dando ao cliente uma cópia com tudo o que o log habilitado, ajudando a rastrear onde eles estão tendo problemas.

Use um logger como log4net que você pode apresentar a sua base de código existente com < a href = "http://www.postsharp.org/" rel = "nofollow noreferrer"> PostSharp . Registrar todas as entradas de método e saídas - por isso você deve encontrar o método defeituoso. Depois, você pode melhorar o seu log se ele ainda é necessária.

Parece que este está a trabalhar para vb.net, também, embora eu não tenho nenhuma experiência lá. Talvez este artigo ajuda -lhe um pouco.

Você vai ter que entrevistar os clientes muito bem. Isso nem sempre é fácil, mas é a sua única chance de estreitar o baixo problema.

Em seguida, adicione cuidadosamente rastreamento, e não se esqueça de liberar em pontos estratégicos (ou conjunto AutoFlush).

Mas poderia ser um problema de tempo sutil que vai embora devido ao atraso adicional de rastreamento ...

Pode haver um problema com CPUs multi-core single-core e de se comportar de forma diferente, por exemplo, quando uma discussão de fundo tenta atualizar a interface do usuário.

(E eu admito que eu escrevi uma volta aplicativo na idade das trevas que não o fizeram de forma limpa separados tópicos de fundo e interface do usuário e os problemas causados ??quando CPUs multi-core tem mainstream. A solução foi chamar o SetProcessAffinity para restringir o aplicativo para um single core)

Se for esse o caso, você deve verificar se a CPU 100% ocorre apenas com um tipo especial de CPU, e se utilizando resolve SetProcessAffinity o problema. Se isso acontecer, você sabe onde procurar em seu código.

Poderia ser um problema de threading? "Falha intermitentemente" marcas me pensar nisso. O programa recebe sinais / mensagens do lado de fora, como remoting / DCOM / soquetes? é um progresso informações relacionadas com tais mensagens apresentada no usuário interface?

Eu uma vez detectado um problema de threading, porque eu sempre usar um monte de ASSERTs. Houve um ASSERT verificação de sanidade para o início de uma mensagem recebida através de XML-RPC para ser:

"<?xml " 

eo ASSERT catched uma substituição da memória da mensagem. De inspeção acabou por ser devido um bloqueio faltando em um seção Crítica. Esta detecção só foi possível porque o problema foi apresado tão cedo pela ASSERT (e aconteceu suficientemente muitas vezes de ser detectado).

Este não é um conselho muito specfific ou dirigida, mas meu sugestão então é adicionar ASSERTs em lugares que podem ser afetou um problema threading.

Note que o disparo ASSERTs não implica necessariamente abortar o programa ou caixas de mensagem de lance. ASSERTs pode ser redirecionado para um arquivo de log em vez disso, incluindo a pilha completa traçar no momento do disparo ASSERT.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top