void *fdserver(void *data) { int fd; EMsg *msg; int id = (int)data; fd_set rfds; fd = e_msgport_fd(server_port); while (1) { int count = 0; printf("server %d: waiting on fd %d\n", id, fd); FD_ZERO(&rfds); FD_SET(fd, &rfds); select(fd+1, &rfds, NULL, NULL, NULL); printf("server %d: Got async notification, checking for messages\n", id); while ((msg = e_msgport_get(server_port))) { printf("server %d: got message\n", id); g_usleep(1000000); printf("server %d: replying\n", id); e_msgport_reply(msg); count++; } printf("server %d: got %d messages\n", id, count); } }
/** * camel_operation_cancel_fd: * @cc: operation context * * Retrieve a file descriptor that can be waited on (select, or poll) * for read, to asynchronously detect cancellation. * * Return value: The fd, or -1 if cancellation is not available * (blocked, or has not been registered for this thread). **/ int camel_operation_cancel_fd (CamelOperation *cc) { if (cc == NULL) cc = co_getcc(); if (cc == NULL || cc->blocked) return -1; LOCK(); if (cc->cancel_fd == -1) cc->cancel_fd = e_msgport_fd(cc->cancel_port); UNLOCK(); return cc->cancel_fd; }
/* returns -1 if we didn't wait for reply from thread */ static int cs_waitinfo(void *(worker)(void *), struct _addrinfo_msg *msg, const char *error, CamelException *ex) { EMsgPort *reply_port; pthread_t id; int err, cancel_fd, cancel = 0, fd; cancel_fd = camel_operation_cancel_fd(NULL); if (cancel_fd == -1) { worker(msg); return 0; } reply_port = msg->msg.reply_port = e_msgport_new(); fd = e_msgport_fd(msg->msg.reply_port); if ((err = pthread_create(&id, NULL, worker, msg)) == 0) { int status; #ifndef G_OS_WIN32 struct pollfd polls[2]; polls[0].fd = fd; polls[0].events = POLLIN; polls[1].fd = cancel_fd; polls[1].events = POLLIN; d(printf("waiting for name return/cancellation in main process\n")); do { polls[0].revents = 0; polls[1].revents = 0; status = poll(polls, 2, -1); } while (status == -1 && errno == EINTR); #else fd_set read_set; FD_ZERO(&read_set); FD_SET(fd, &read_set); FD_SET(cancel_fd, &read_set); status = select(MAX(fd, cancel_fd) + 1, &read_set, NULL, NULL, NULL); #endif if (status == -1 || #ifndef G_OS_WIN32 (polls[1].revents & POLLIN) #else FD_ISSET (cancel_fd, &read_set) #endif ) { if (status == -1) camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, "%s: %s", error, #ifndef G_OS_WIN32 g_strerror(errno) #else g_win32_error_message (WSAGetLastError ()) #endif ); else camel_exception_setv(ex, CAMEL_EXCEPTION_USER_CANCEL, _("Canceled")); /* We cancel so if the thread impl is decent it causes immediate exit. We detach so we dont need to wait for it to exit if it isn't. We check the reply port incase we had a reply in the mean time, which we free later */ d(printf("Canceling lookup thread and leaving it\n")); msg->cancelled = 1; pthread_detach(id); pthread_cancel(id); cancel = 1; } else { struct _addrinfo_msg *reply = (struct _addrinfo_msg *)e_msgport_get(reply_port); g_assert(reply == msg); d(printf("waiting for child to exit\n")); pthread_join(id, NULL); d(printf("child done\n")); } } else { camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, "%s: %s: %s", error, _("cannot create thread"), g_strerror(err)); } e_msgport_destroy(reply_port); return cancel; }