J'ai un programme qui obtient une KERN_PROTECTION_FAILURE avec EXC_BAD_ACCESS dans un endroit très étrange lors de l'exécution multithread et je n'ai pas la moindre idée sur la façon de résoudre le problème plus loin. C'est sur MacOS 10.6 en utilisant GCC.Besoin d'aide pour le suivi EXC_BAD_ACCESS sur la fonction Entrée sur MacOS
L'endroit très étrange qu'il obtient est lors de l'entrée d'une fonction. Pas sur la première ligne de la fonction, mais le saut réel à la fonction GetMachineFactors():
Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_PROTECTION_FAILURE at address: 0xb00009ec
[Switching to process 28242]
0x00012592 in GetMachineFactors() at ../sysinfo/OSX.cpp:168
168 MachineFactors* GetMachineFactors()
(gdb) bt
#0 0x00012592 in GetMachineFactors() at ../sysinfo/OSX.cpp:168
#1 0x000156d0 in CollectMachineFactorsThreadProc (parameter=0x200280) at Threads.cpp:341
#2 0x952f681d in _pthread_start()
#3 0x952f66a2 in thread_start()
(gdb)
Si je lance ce non-thread, il fonctionne très bien, aucun problème:
#include "MachineFactors.h"
int main(int argc, char** argv)
{
MachineFactors* factors = GetMachineFactors();
std::string str = CreateJSONObject(factors);
cout << str;
delete factors;
return 0;
}
Si Je cours ceci dans un pthread, j'obtiens le EXC_BAD_ACCESS ci-dessus.
THREAD_FUNCTION CollectMachineFactorsThreadProc(LPVOID parameter)
{
Main* client = (Main*) parameter;
if (parameter == NULL)
{
ERRORLOG("No data passed to machine identification thread. Aborting.");
return 0;
}
MachineFactors* mfactors = GetMachineFactors(); // This is where it dies.
// If I don't call GetMachineFactors and do something like mfactors =
// new MachineFactors(); everything is good and the threads communicate and exit
// normally.
if (mfactors == NULL)
{
ERRORLOG("Failed to collect machine identification: GetMachineFactors returned NULL." << endl)
return 0;
}
client->machineFactors = CreateJSONObject(mfactors);
delete mfactors;
EVENT_RAISE(client->machineFactorsEvent);
return 0;
}
Voici un extrait du GetMachineFactors() Code:
MachineFactors* GetMachineFactors() // Dies on this line in multi-threaded.
{
// printf("Getting machine factors.\n"); // Tried with and without this, never prints.
factors = new MachineFactors();
factors->OSName = "MacOS";
factors->Manufacturer = "Apple";
///…
// gather various machine metrics here.
//…
return factors;
}
Pour référence, je me sers d'une socketpair attendre sur le fil pour compléter:
// From the header file I use for cross-platform defines (this runs on OSX, Windows, and Linux.
struct _waitt
{
int fds[2];
};
#define THREAD_FUNCTION void*
#define THREAD_REFERENCE pthread_t
#define MUTEX_REFERENCE pthread_mutex_t*
#define MUTEX_LOCK(m) pthread_mutex_lock(m)
#define MUTEX_UNLOCK pthread_mutex_unlock
#define EVENT_REFERENCE struct _waitt
#define EVENT_WAIT(m) do { char lc; if (read(m.fds[0], &lc, 1)) {} } while (0)
#define EVENT_RAISE(m) do { char lc = 'j'; if (write(m.fds[1], &lc, 1)) {} } while (0)
#define EVENT_NULL(m) do { m.fds[0] = -1; m.fds[1] = -1; } while (0)
Voici le code où je lance le fil.
void Main::CollectMachineFactors()
{
#ifdef WIN32
machineFactorsThread = CreateThread(NULL, 0, CollectMachineFactorsThreadProc, this, 0, 0);
if (machineFactorsThread == NULL)
{
ERRORLOG("Could not create thread for machine id: " << ERROR_NO << endl)
}
#else
int retval = pthread_create(&machineFactorsThread, NULL, CollectMachineFactorsThreadProc, this);
if (retval)
{
ERRORLOG("Return code from machine id pthread_create() is " << retval << endl)
}
#endif
}
Voici le cas d'échec simple de l'exécution de ce multithread. Il échoue toujours pour ce code avec la trace de pile ci-dessus:
CollectMachineFactors();
EVENT_WAIT(machineFactorsEvent);
cout << machineFactors;
return 0;
Au début, j'ai suspecté un problème de bibliothèque. Voici mon makefile:
# Main executable file
PROGRAM = sysinfo
# Object files
OBJECTS = Version.h Main.o Protocol.o Socket.o SSLConnection.o Stats.o TimeElapsed.o Formatter.o OSX.o Threads.o
# Include directories
INCLUDE = -Itaocrypt/include -IyaSSL/taocrypt/mySTL -IyaSSL/include -isysroot /Developer/SDKs/MacOSX10.5.sdk -mmacosx-version-min=10.5
# Library settings
STATICLIBS = libtaocrypt.a libyassl.a -Wl,-rpath,. -ldl -lpthread -lz -lexpat
# Compile settings
RELCXX = g++ -g -ggdb -DDEBUG -Wall $(INCLUDE)
.SUFFIXES: .o .cpp
.cpp.o :
$(RELCXX) -c -Wall $(INCLUDE) -o [email protected] $<
all: $(PROGRAM)
$(PROGRAM): $(OBJECTS)
$(RELCXX) -o $(PROGRAM) $(OBJECTS) $(STATICLIBS)
clean:
rm -f *.o $(PROGRAM)
Je ne peux pas pour la vie de me voir tout particulièrement étrange ou dangereux et je ne suis pas sûr où regarder. Le même processus threadé fonctionne très bien sur toutes les machines Linux que j'ai essayées. Aucune suggestion? Tous les outils que je devrais essayer?
Je peux ajouter plus d'informations si ce serait utile.
Merci d'avoir essayé, mais il s'est avéré être l'un de ces «problèmes inexplicables étranges» qui nécessitaient un fork() pour se comporter correctement. –