web-dev-qa-db-fra.com

Quand un processus obtient-il SIGABRT (signal 6)?

Quels sont les scénarios dans lesquels un processus obtient un SIGABRT en C++? Ce signal provient-il toujours du processus ou peut-il être envoyé d'un processus à un autre?

Existe-t-il un moyen d'identifier quel processus envoie ce signal?

182
Shree

abort() envoie au processus appelant le signal SIGABRT, voici comment abort() fonctionne.

abort() est généralement appelé par les fonctions de la bibliothèque qui détectent une erreur interne ou une contrainte sérieusement rompue. Par exemple, malloc() appellera abort() si ses structures internes sont endommagées par un débordement de tas.

174
Nordic Mainframe

Vous pouvez envoyer n'importe quel signal à n'importe quel processus à l'aide de l'interface kill(2):

kill -SIGABRT 30823

30823 était un processus dash que j'avais commencé afin de pouvoir facilement trouver le processus que je voulais tuer.

$ /bin/dash
$ Aborted

La sortie Aborted indique apparemment comment dash rapporte un SIGABRT.

Il peut être envoyé directement à tout processus à l'aide de kill(2), ou un processus peut s'envoyer le signal via lui-même via assert(3), abort(3) ou raise(3).

49
sarnold

SIGABRT est couramment utilisé par la libc et d'autres bibliothèques pour abandonner le programme en cas d'erreur critique. Par exemple, glibc envoie un SIGABRT en cas de corruption détectée à double réserve ou autre.

De plus, la plupart des implémentations assert utilisent SIGABRT en cas d’échec de la déclaration.

De plus, SIGABRT peut être envoyé à partir de tout autre processus, à l'instar de tout autre signal. Bien sûr, le processus d'envoi doit être exécuté avec le même utilisateur ou le même utilisateur root.

47
IanH

Cela se produit généralement lorsqu'il y a un problème d'allocation de mémoire.

Cela m'est arrivé lorsque mon programme tentait d'allouer un tableau de taille négative.

16
Mig

Il y a une autre cause simple dans le cas de c ++.

std::thread::~thread{
    if((joinable ())
        std::terminate ();
}

c'est-à-dire que la portée du fil est terminée mais que vous avez oublié d'appeler non plus

thread::join();

ou

thread::detach();
10
Sudip Bhattarai

La GNU libc imprimera des informations à /dev/tty concernant certaines conditions fatales avant d'appeler abort() (qui déclenchera alors SIGABRT), mais si vous exécutez votre programme en tant que service ou autrement pas dans une fenêtre de terminal réelle, ces messages peuvent être perdus, car il n’existe pas de terminal pour afficher les messages.

Voir mon post sur la redirection de libc pour écrire sur stderr au lieu de/dev/tty:

Capture des messages d'erreur libc, redirection de/dev/tty

6
Mark Lakata

Un cas où le processus obtient SIGABRT de lui-même: Hrvoje a parlé d’un appel virtuel pur enterré appelé depuis ctor, générant un abandon, j’ai recréé un exemple pour cela. Ici, lorsque d doit être construit, il appelle d’abord sa classe de base A ctor, puis passe le pointeur interne à lui-même. L'acteur appelle la méthode virtuelle pure avant que la table ne soit remplie avec un pointeur valide, car d n'est pas encore construit.

#include<iostream>
using namespace std;
class A {
public:
 A(A *pa){pa->f();}
 virtual void f()=0;
};
class D : public A {
public:
 D():A(this){}
 virtual void f() {cout<<"D::f\n";}
};
int main(){
 D d;
 A *pa = &d;
 pa->f();
 return 0;
}

compiler: g ++ -o aa aa.cpp

ulimit -c illimité

lancer: ./aa

pure virtual method called
terminate called without an active exception
Aborted (core dumped)

permet maintenant de voir rapidement le fichier core et de valider que SIGABRT a bien été appelé:

gdb aa core

voir regs:

i r
rdx            0x6      6
rsi            0x69a    1690
rdi            0x69a    1690
rip            0x7feae3170c37

code de vérification:

dises 0x7feae3170c37

mov    $0xea,%eax  = 234  <- this is the kill syscall, sends signal to process
syscall   <-----

http://blog.rchapman.org/posts/Linux_System_Call_Table_for_x86_64/

234 sys_tgkill pid_t tgid pid_t pid int sig = 6 = SIGABRT

:)

3
Alexander Kruman

Dans mon cas, cela était dû à une entrée dans un tableau à un index égal à la longueur du tableau.

string x[5];

for(int i=1; i<=5; i++){

    cin>>x[i];

}

on accède à x [5] qui n'est pas présent.

1
anonymous