View Full Version : [C/Unix]SIGSEGV su pthread_join()
Salve,
sono di nuovo alle prese con il threading in Unix.
Probabilmente sono sfortunato, ma non funziona una cippa come dovrebbe.
In questo caso, la chiamata a pthread_join fallisce miseramente con una SIGSEGV ogniqualvolta venga chiamata.
Nel progetto wrappo la chiamata in questo modo:
int thread_join( int TID )
{
DEBUG_ASSERT( TID != 0 );
return NOERROR( pthread_join( (pthread_t)TID, NULL ) );
}
Sono sicuro che:
-i thread vengono fatti partire con successo
-succede sia se sono in esecuzione, sia se sono in wait, sia se sono terminati
-TID in ingresso è effettivamente il pthread_t restituito da pthread_create
Però in _qualsiasi_ modo io chiami pthread_join, mi becco una SIGSEGV.
Mistero :muro: :muro:
EDIT:
se chiamo pthread_join(0,0), inspiegabilmente, funziona. Quindi vuol dire che proprio quei TID che sto provando a chiamare io non sono validi... deve esserci un qualche errore alla creazione, perchè il thread viene creato ed è valido, ma il pthread_t ritornato no.
int thread_start( void(*runnableFunction)(void*), void* buf )
{
int error;
pthread_t TID;
void*(*start_routine)(void*) = (void*(*)(void*))runnableFunction;
DEBUG_ASSERT( runnableFunction );
error = pthread_create(
&TID,
NULL,
start_routine,
buf );
return (error==0) ? (int)TID : 0;
}
Qualcuno mi salvi! :asd:
Non riesco a trovare il modo di farlo andare...
mi andrebbe bene anche un link ad un forum internazionale più adeguato a questi argomenti!
Non fatemi scomodare il prof :asd:
boh di certo non capisco perché usi int invece di pthread_t, sei così sicuro che pthread_t sia definito come int? cercando in giro non ho trovato molto, solo questo (http://refspecs.freestandards.org/LSB_3.1.1/LSB-Core-generic/LSB-Core-generic/libpthread-ddefs.html) in cui è definito come unsigned long (questo spiegherebbe perché il valore che ritorni non è valido)
Sono convinto anche io che il problema stia nel fatto che mescoli pthread_t ed int.
In particolare e' facile che in una macchina a 64 bit quel pthread_t sia a 64 bit, con tutte le conseguenze del caso.
Non mescolare, hai alternative piu' sane a disposizione che non ritornare uno 0 in caso di fallimento, come lanciare un'eccezione, ritornare un puntatore a un pthread_t o ritornare solo lo stato di errore (come fa pthread_create) ed accettare il pthread_t come argomento.
uhm... faccio il cast ad int per una questione di compatibilità: la stessa funzione su Win32 fa un cast di una HANDLE.
int agisce da "contenitore opaco" rispetto all'user, che lo può usare come identificatore.
Quindi
-non posso lanciare un'eccezione (C liscio)
-non posso parlare esplicitamente di pthread_t
Però se è vero che il problema è il tipo di dato, potrei definire un tipo thread_t definito come pthread_t su Unix e come HANDLE su Win32.
Oppure usare long invece che int, così se ne occupa direttamente il compilatore.
Alla fine mi sembra sia la cosa più sana.
EDIT: usando "#define thread_t unsigned long" funziona alla perfezione su tutti i SO, grazie mille :D
Il problema era molto più stupido del previsto :read:
ancora però, sei sicuro che sia generico a sufficienza? io fossi in te, se dovessi fare una qualche sorta di libreria cross platform per i thread userei una struttura dati che mappi il tipo del thread id con un intero, tipo map<int, pthread_t (o HANDLE)> per dirlo in termini di c++
così puoi rifarti alla definizione di pthread_t e HANDLE e usare un tuo tipo come "handle"
Sicuramente si, sarebbe la cosa migliore... sicuramente in C++, dove è più gestibile, l'avrei fatto.. in è più difficile da mantenere.
E poi col "rischio" tutto si riduce a un cast, mentre con le strutture dati ho anche un costo di ricerca :read:
EDIT: usando "#define thread_t unsigned long" funziona alla perfezione su
tutti i SO, grazie mille :D
Perche' allora non utilizzare direttamente pthread_t invece che l'unsigned long ? (E magari un typedef, o una struttura opaca)
[/QUOTE]
Perche' allora non utilizzare direttamente pthread_t invece che l'unsigned long ? (E magari un typedef, o una struttura opaca)
Per il semplice fatto che pthread_t è di dimensione diversa da HANDLE.
Quindi se creo pthread_t[100] quello è grosso 800b su architetture x64, ma HANDLE[100] è sempre grosso 400 perchè è proprio un'int.
E questo può generare dei comportamenti imprevedibili lato utente che con long mi risparmio.
Tanto sprecare 4 byte su un'handle non credo proprio che sia un problema.
credo che voglia dire una cosa tipo
typedef pthread_t mythread_t;
su linux e
typedef HANDLE mythread_t;
su windows
e thread_join ritorna un mythread_t invece di un unsigned int in entrambi i casi
credo che voglia dire una cosa tipo
typedef pthread_t mythread_t;
su linux e
typedef HANDLE mythread_t;
su windows
e thread_join ritorna un mythread_t invece di un unsigned int in entrambi i casi
Si' esatto. Se la dimensione differente tra le due piattaforme e' un problema (ma non dovrebbe esserlo, perche' comunque le cose cambiano tra 32 e 64, sizeof(pthread_t) e' 4 sotto i 32 bit), si puo' usare una union in modo da richiedere lo spazio necessario.
typedef union
{
#if defined(WIN32) /* o _WIN32 ? Non ricordo :D */
HANDLE handle;
#elif defined(__unix__) /* Non standard, ma non ricordo la macro corretta... :P */
pthread_t handle;
#endif
char _filler[8];
} mythread_t;
Meno rischiosa che cast a manetta (anche se, secondo me, inutile).
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.