Example #1
0
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;
}