Pergunta

Eu preciso chamar uma função de biblioteca que às vezes não vai terminar dentro de um determinado tempo, infelizmente. Existe uma maneira de chamar a função, mas abort-lo se ele não terminar dentro de segundos n?

Não posso modificar a função, então eu não posso colocar a condição abort para ele diretamente. Eu tenho que adicionar um tempo limite para a função externamente .

É talvez uma solução possível para iniciá-lo como um (boost) rosca, que pode, então, terminar depois de um certo tempo? Será que algo como isso funciona? Eu realmente acredito que a função é não thread-safe, mas isso não importa se eu executá-lo como o única único segmento, certo? Existem outros (melhor) soluções?

Foi útil?

Solução

Você poderia gerar um boost::thread para chamar a API:

boost::thread api_caller(::api_function, arg1, arg2);
if (api_caller.timed_join(boost::posix_time::milliseconds(500)))
{
    // API call returned within 500ms
}
else
{
    // API call timed out
}

Aumento não permite que você para matar o segmento de trabalho, no entanto. Neste exemplo, é só órfão.

Você vai ter que ser cuidadoso sobre o que chamada de API faz, porque nunca pode liberar recursos é adquirido.

Outras dicas

Eu acho que a única maneira segura de fazer isso seria a de gerar um separado sandbox processo que chama a função de biblioteca como um proxy para a sua aplicação. Você precisa implementar algum tipo de IPC entre seu aplicativo e o proxy. A implementação de um tempo limite ao ler a resposta IPC é então bastante trivial. Se a leitura falhar devido ao tempo limite, então você pode seguramente terminar o proxy sem arriscar a saúde de sua aplicação.

O que você está falando é normalmente chamado um sistema de "cão de guarda". O cão de guarda é, tipicamente, um segundo fio que verificações sobre o estado de todos os outros segmentos. A agência geralmente é configurado para ser executado periodicamente. Se nenhuma resposta foi recebida de outros tópicos, o cão de guarda pode notificar o usuário, ou mesmo matar o fio agressor se é possível fazê-lo com segurança (depende da sua aplicação).

O problema com tópicos é que alguns recursos que você não será capaz de libertar após o término fio. Se você não adquirir recursos que você tem que liberar, em seguida, ir com threads.

O problema é que, com uma solução in-process sem o apoio da função você acabar com o estado potencialmente inválido.

Exemplo:. Quando você terminar a thread enquanto uma alocação de memória está ocorrendo, sua pilha de processo pode ser corrompido

Assim que você pode encerrar a ligação, mas então você também tem que terminar o processo. Em muitos casos, as chances de efeitos colaterais destrutivos são pequenos, mas eu não apostaria meu cálculo sobre isso.

Você pode, como Ben Straub sugere, apenas órfão o tópico: colocá-lo em prioridade mais baixa e que partem para o infinito. Isso é, naturalmente, apenas uma solução limitada:. Se os ressources consome rosca (provável), que vai abrandar o sistema, também há um limite para threads por processo (geralmente devido a espaço de endereço para segmento de pilha)

Geralmente, eu prefiro a solução processo externo. Um padrão simples é esta:
de dados de escrita de entrada para um arquivo, inicie o processo externo com o arquivo como argumento. O processo externo escreve progresso (se houver) para um arquivo em disco que pode ser monitorado, e pode até permitir que o processo para retomar de onde começou. Os resultados são gravados no disco, e o processo pai pode ler-los.

Quando você terminar o processo, você ainda tem que lidar com a sincronização de acesso a Recursos externos (como arquivos), e como lidar com mutices abandonadas, arquivos escritos à meia etc. Mas é geralmente o caminho para uma solução robusta.

O que você precisa é de uma linha e uma Futuro objeto que pode segurar o resultam da chamada de função.

Para um exemplo usando boost ver aqui .

Você precisa verificar o futuro após o tempo limite e se não for definido, agir em conformidade.

Vá com um processo órfão, lançá-lo e tempo de sua execução. Se ele é executado fora do tempo, invocar o OS para matá-lo.

Como evitar Conds corrida. neste padrão:

  • criar um arquivo para armazenar em args (claro, tudo é repassado como Vals). O processo órfão só é permitido para ler dados a partir deste arquivo.

  • O órfão processa os dados de entrada, cria um ficheiro de saída com valores de resultados e fecha-o.

  • Somente quando tudo é feito, órfão exclui o arquivo de entrada, um fato que os sinais do processo mestre que o trabalho foi feito.

Esta leitura escrita à metade problema arquivos, uma vez que o mestre primeiros avisos absense de arquivo de entrada evita, abre para ler o arquivo de saída, que é certamente concluída (porque foi fechado antes de eliminar entrada e pilhas de chamadas OS são sequenciais).

"Eu preciso chamar uma função de biblioteca que às vezes não vai terminar dentro de um determinado tempo, infelizmente. Existe uma maneira de chamar a função, mas abort-lo se ele não terminar dentro de n segundos?"

A resposta curta não é. Isso é geralmente o problema ... A chamada em si deve terminar em algum momento (implementação do seu próprio tempo limite), mas chamadas de bloqueio são geralmente problemas (por exemplo, gethostbyname ()), porque então cabe a sua (ou sistema) de tempo limite, não seu.

Assim, sempre que possível, tentar fazer o código em execução na saída de segmento limpa quando necessário - o próprio código deve detectar e tratar o erro. Pode enviar uma mensagem e / ou conjunto de estados de modo que o principal (ou aother) Rosca sabe o que se passou.

A preferência pessoal, em sistemas altamente disponíveis, eu como os meus tópicos girando frequentemente (não ocupado-locking embora) com limites de tempo específicos, chamando funções sem bloqueio, e com condições de saída precisas no lugar. A-específica fio global ou 'feito' variável faz o truque para uma saída limpa.

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