with tutorial framework español djangoproject desde con cero applications c gcc compiler-errors pthreads

c - framework - tutorial django



Cómo reparar el error de gcc: esperado mientras que antes el vacío (2)

Tuve el mismo problema y al agregar pthread_cleanup_pop(1) resolví.

Así que estoy escribiendo un cliente de chat peer-to-peer que usa pthreads para administrar todo el IO y cuando compilo el archivo gcc me da el error

client.c: In function ‘accepted_daemon’: client.c:115:1: error: expected ‘while’ before ‘void’ void * ^ client.c: In function ‘listen_daemon’: client.c:176:1: error: expected ‘while’ before ‘int’ int main(int argc, char *argv[]) ^

El código fuente de mi programa es

#include <stdlib.h> #include <string.h> #include <stdint.h> #include <errno.h> #include <assert.h> #include <unistd.h> #include <pthread.h> #include <readline/readline.h> #include <error.h> #define error(s, e, ...) error_at_line (s, e, __FILE__, __LINE__, __VA_ARGS__) #include <sys/socket.h> #include <arpa/inet.h> #include <netinet/in.h> #include <netdb.h> #define PORT 3248 #define PROMPT "message: " struct accepted { int fd; struct sockaddr_in addr; }; struct value { struct accepted *acc; struct value *nxt; }; pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; struct value *remote = NULL; void push_remote (struct accepted *acc) { pthread_mutex_lock (&mutex); struct value *s = malloc (sizeof *s); s->acc = acc; s->nxt = remote; remote = s; pthread_mutex_unlock (&mutex); } void pop_remote (struct accepted *acc) { pthread_mutex_lock (&mutex); struct value head = { NULL, remote }; struct value *s = &head; while (s->nxt->acc != acc) { s = s->nxt; if (s->nxt == NULL) return; } struct value *tmp = s->nxt->nxt; free (s->nxt); s->nxt = tmp; } struct accepted * make_socket (uint32_t s_addr) { struct accepted *addr = malloc (sizeof *addr); addr->fd = socket (PF_INET, SOCK_STREAM, 0); if (addr->fd < 0) { free (addr); return NULL; } addr->addr.sin_family = AF_INET; addr->addr.sin_port = htons (PORT); addr->addr.sin_addr.s_addr = s_addr; if (connect (addr->fd, (struct sockaddr *) &addr->addr, sizeof addr->addr) < 0) { free (addr); return NULL; } return addr; } void * accepted_daemon (void *arg) { pthread_cleanup_push (free, arg); struct accepted *args = arg; pthread_cleanup_push (close, args->fd); push_remote (args); pthread_cleanup_push (pop_remote, args); while (1) { char buffer[100]; ssize_t chars = read (args->fd, buffer, sizeof buffer); if (chars < 0) { error (0, errno, "Host %s disconnected", inet_ntop (AF_INET, arg, buffer, sizeof buffer)); return NULL; } write (1, buffer, chars); write (1, "/n", strlen ("/n") * sizeof (char)); } return NULL; } void * initial_connection (void *arg) { uint32_t host = (uint32_t) arg; struct accepted *acc = make_socket (arg); if (acc == NULL) { char buffer[100]; error (1, errno, "Failed to connect to host %s", inet_ntop (AF_INET, arg, buffer, sizeof buffer)); } while (1) { uint32_t nxthost; read (sock, &nxthost, sizeof nxthost); if (nxthost == 0) break; pthread_t thread; pthread_create (&thread, NULL, initial_connection, (void *) nxthost); } return accepted_daemon (acc); } void * listen_daemon (void *arg) { int sock = socket (PF_INET, SOCK_STREAM, 0); pthread_cleanup_push (close, sock); struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_port = htons (PORT); addr.sin_addr.s_addr = INADDR_ANY; bind (sock, (struct sockaddr *) &addr, sizeof addr); listen (sock, 5); while (1) { struct accepted *acc = malloc (sizeof *acc); socklen_t len; acc->fd = accept (sock, (struct sockaddr *) &acc->addr, &len); pthread_mutex_lock (&mutex); struct value *p = remote; while (p != NULL) { write (acc->fd, &p->acc->addr.sin_addr.s_addr, sizeof (uint32_t)); p = p->nxt; } pthread_mutex_unlock (&mutex); pthread_t thread; pthread_create (&thread, NULL, accepted_daemon, (void *) acc); } return NULL; } int main(int argc, char *argv[]) { assert (argc == 2); struct hostent *target = gethostbyname2 (argv[1], AF_INET); if (target == NULL) error (1, errno, "Host could not be found"); pthread_t thread; pthread_create (&thread, NULL, initial_connection, (void *) inet_addr (target->h_addr)); pthread_create (&thread, NULL, listen_daemon, NULL); char *in = readline (PROMPT); while (in != NULL) { pthread_mutex_lock (&mutex); struct value *p = remote; while (p != NULL) { write (p->addr->fd, in, strlen (in)); p = p->nxt; } pthread_mutex_unlock (&mutex); free (in); in = readline (PROMPT); } return 0; }


pthread_cleanup_push() probablemente se implemente como una macro que introduce una llave abierta { que espera una (correspondiente) pthread_cleanup_pop() en el mismo contexto. Este último luego sirve la llave de cierre } . * 1

Eche un vistazo a la salida de preprocesador del código (y en las páginas man y los archivos de encabezado, por supuesto) y obtendrá información.

* 1 Este tipo de implementación, BTW, es la forma más rigurosa que he visto para disciplinar a los codificadores de C ...; ->