PDA

Visualizza la versione completa : [C] thread linux


Hysoka
02-01-2009, 16:13
ciao a tutti,
seguo il corso di sistemi distribuiti nella mia università e non riesco a creare un thread linux. Ma a me il codice pare a prova di imbecille (ovvero me), ma intanto non va!

Posto tutti il codice

struct InetClient
{
int socket;
struct sockaddr_in address;
int addressLength;
};

void ClientLister (void * );


int main(int argc, char** argv)
{
int serverSocket,clientAddrLength;
struct sockaddr_in qualsiasi, clientAddr;

qualsiasi.sin_family = AF_INET;
qualsiasi.sin_port = htons(4000);
qualsiasi.sin_addr.s_addr = INADDR_ANY;

serverSocket = socket(PF_INET, SOCK_STREAM, 0);
bind(serverSocket, (struct sockaddr *)&qualsiasi, sizeof ( qualsiasi));
listen(serverSocket,0);

while (1)
{
clientAddrLength = sizeof(struct sockaddr_in);
printf("Waiting for client...\n");
int clientSocket = accept(serverSocket, (struct sockaddr *)&clientAddr, &clientAddrLength);
printf("Client connected\n");

struct InetClient * client = (struct InetClient*) malloc(sizeof(struct InetClient*));
client->socket = clientSocket;
client->address = clientAddr;
client->addressLength = clientAddrLength;

pthread_t *nuovoThread = (pthread_t*)malloc(sizeof(pthread_t));

pthread_create(nuovoThread,NULL,(void*)&ClientLister,(void*)&client);
}

return 0;
}

void ClientLister(void * arg)
{
struct InetClient client = *((struct InetClient *) arg);
printf("Eccomi qua");
}

con telnel riesco a connettermi su questo server. Essendo sistemi distribuiti, sto coniugando socket C e thread linux in un sol colpo....
l'output aspettato da questo programma è qualcosa tipo:

Waiting for a client...
Client connected
Waiting for a client...
Eccomi qua


ma niente...sembra che il thread non parta, anzi non parte proprio...
Ho provato a fare una join, ma non parte ugualmente e la join non esulerebbe dal mio scopo...
cosa sbaglio?

Socket problemi non ne danno e la creazione dei thread non prende più di 2 righe di codice, ma intanto non va...

suggerimenti?
vi ringrazio anticipatamente

Hysoka
04-01-2009, 13:06
nessuno sa aiutarmi?

MacApp
04-01-2009, 13:19
Il codice che hai postato non è compilabile.

shodan
04-01-2009, 13:34
E pure sbagliato.


...
struct InetClient * client = (struct InetClient*) malloc(sizeof(struct InetClient*));
...

Dovrebbe essere:


...
struct InetClient * client = (struct InetClient*) malloc(sizeof(struct InetClient)); << senza *
...

Poi


...
pthread_create(nuovoThread,NULL,(void*)&ClientLister,(void*)&client);
...

Dovrebbe essere:


...
pthread_create(nuovoThread,NULL,ClientLister,clien t);
...

Senza contare che non ti preoccupi troppo della gestione della memoria. Dove sono deallocate le strutture di cui fai la malloc?

Hysoka
04-01-2009, 13:50
a me compila...
l'errore del malloc è corretto, ma non capisco dove ho sbagliato nel pthread create?
pthread create prende una sfilza di puntatori (tra l'altro, a void)

forse non vi compila xke nn ho postato gli header, che sono:

#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <pthread.h>

shodan
04-01-2009, 14:00
http://opengroup.org/onlinepubs/007908799/xsh/pthread_create.html

pthread_create prende come terzo parametro un puntatore a funzione, mentre tu casti quel puntatore a void* il che è sbagliato. Il quarto parametro poi è già un puntatore e al massimo andrebbe scritto come (void*) client, mentre tu passi qualcosa come:

struct InetClient** tmp = &client;
(void*) tmp;

il che non ha molto senso.

Hysoka
04-01-2009, 14:11
ti ringrazio shodan...
ti posso dire che mettendo (void *)&ClientListener, o mettendo solo ClientListener, il thread parte comunque, solo che come mi ha suggerito tu ricevo un warning...
Effettivamente client è già un puntatore, ed era visibilmente sbagliato quel che facevo, infatti ora riesco a ricevere i dati dalla socket...
ti ringrazio per le dritte....
una domanda: ClientListener, o qualsiasi altro identificatore di funzione, è un puntatore già così?
Nelle slide del mio prof, lui suggerisce (void*)&Funzione...
cosa c'è di sbagliato?

shodan
04-01-2009, 14:46
Una funzione di per se è già un puntatore (il cui tipo dipende dal tipo di ritorno e dai parametri che prende.)
La forma corretta (e rindondante) sarebbe (nel tuo caso) &ClientListener, mentre ClientListener è una forma abbreviata. E' quel (void*) che può creare problemi in quanto altera il tipo corretto di puntatore a funzione, in un puntatore a "tutto".
Nel caso della pthread_create probabilmente quell'argomento viene ricastato al tipo originale, ma fare queste assunzioni è pericoloso in quanto le singole implementazoni possono differire.
In generale è sempre meglio evitare i cast rindondandi, lasciando eventualmente che sia il compilatore a protestare. Metterne uno di troppo, rischia di far impazzire il programmatore.

MacApp
04-01-2009, 16:30
$ man pthread_create:


int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine)(void *), void *arg);


insomma la tua ClientLister e':



void ClientLister (void * );


ma dovrebbe essere:


void * ClientLister (void * );

Loading