aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhiro <hiro@ee746299-78ed-0310-b773-934348b2243d>2007-01-22 08:10:11 +0000
committerhiro <hiro@ee746299-78ed-0310-b773-934348b2243d>2007-01-22 08:10:11 +0000
commit2a1835bfa4813590131f9da2d511bbbcdad15717 (patch)
tree73c58f4ac769cbe75554408d655dfde5bc1071fa
parent3145665c922ead3c2de272eb0ad54c30c228046b (diff)
prevented WSAEWOULDBLOCK on sending/receiving in Win32.
git-svn-id: svn://sylpheed.sraoss.jp/sylpheed/trunk@1500 ee746299-78ed-0310-b773-934348b2243d
-rw-r--r--ChangeLog7
-rw-r--r--ChangeLog.ja8
-rw-r--r--libsylph/session.c5
-rw-r--r--libsylph/socket.c51
-rw-r--r--libsylph/socket.h15
5 files changed, 71 insertions, 15 deletions
diff --git a/ChangeLog b/ChangeLog
index d25147b5..f43bfba2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2007-01-22
+
+ * libsylph/session.c: session_ping_cb(): prohibit blocking here.
+ libsylph/socket.[ch]: added SockFlags as a member of SockInfo.
+ fd_check_io(): select() sockets if SOCK_CHECK_IO flag is up even if
+ in non-blocking mode (prevents WSAEWOULDBLOCK in Win32).
+
2007-01-19
* libsylph/session.c
diff --git a/ChangeLog.ja b/ChangeLog.ja
index ce70fc60..216a73aa 100644
--- a/ChangeLog.ja
+++ b/ChangeLog.ja
@@ -1,3 +1,11 @@
+2007-01-22
+
+ * libsylph/session.c: session_ping_cb(): ここではブロッキングを回避。
+ libsylph/socket.[ch]: SockInfo のメンバに SockFlags を追加。
+ fd_check_io(): 非ブロッキングモードでも SOCK_CHECK_IO フラグが立って
+ いたらソケットを select() するようにした(Win32 で WSAEWOULDBLOCK
+ を回避)。
+
2007-01-19
* libsylph/session.c
diff --git a/libsylph/session.c b/libsylph/session.c
index 73691dca..5ebb564d 100644
--- a/libsylph/session.c
+++ b/libsylph/session.c
@@ -276,8 +276,13 @@ static gboolean session_ping_cb(gpointer data)
}
if (tv_result.tv_sec * G_USEC_PER_SEC + tv_result.tv_usec >
G_USEC_PER_SEC) {
+ SockFlags save_flags;
+
debug_print("state machine freeze for 1 second detected, forcing dispatch.\n");
+ save_flags = sock->flags;
+ SOCK_UNSET_FLAGS(sock->flags, SOCK_CHECK_IO);
sock->callback(sock, sock->condition, sock->data);
+ sock->flags = save_flags;
}
}
diff --git a/libsylph/socket.c b/libsylph/socket.c
index 189c1b77..3409b0e9 100644
--- a/libsylph/socket.c
+++ b/libsylph/socket.c
@@ -380,8 +380,13 @@ static gint set_nonblocking_mode(gint fd, gboolean nonblock)
}
sock = sock_find_from_fd(fd);
- if (sock)
- sock->nonblock = nonblock;
+ if (sock) {
+ if (nonblock) {
+ SOCK_SET_FLAGS(sock->flags, SOCK_NONBLOCK);
+ } else {
+ SOCK_UNSET_FLAGS(sock->flags, SOCK_NONBLOCK);
+ }
+ }
debug_print("set nonblocking mode to %d\n", nonblock);
return 0;
@@ -410,8 +415,13 @@ gint sock_set_nonblocking_mode(SockInfo *sock, gboolean nonblock)
g_return_val_if_fail(sock != NULL, -1);
ret = set_nonblocking_mode(sock->sock, nonblock);
- if (ret == 0)
- sock->nonblock = nonblock;
+ if (ret == 0) {
+ if (nonblock) {
+ SOCK_SET_FLAGS(sock->flags, SOCK_NONBLOCK);
+ } else {
+ SOCK_UNSET_FLAGS(sock->flags, SOCK_NONBLOCK);
+ }
+ }
return ret;
}
@@ -422,8 +432,9 @@ static gboolean is_nonblocking_mode(gint fd)
SockInfo *sock;
sock = sock_find_from_fd(fd);
- if (sock)
- return sock->nonblock;
+ if (sock) {
+ return SOCK_IS_NONBLOCK(sock->flags);
+ }
return FALSE;
#else
@@ -444,7 +455,7 @@ gboolean sock_is_nonblocking_mode(SockInfo *sock)
g_return_val_if_fail(sock != NULL, FALSE);
#ifdef G_OS_WIN32
- return sock->nonblock;
+ return SOCK_IS_NONBLOCK(sock->flags);
#else
return is_nonblocking_mode(sock->sock);
#endif
@@ -560,8 +571,10 @@ static gint fd_check_io(gint fd, GIOCondition cond)
{
struct timeval timeout;
fd_set fds;
+ SockInfo *sock;
- if (is_nonblocking_mode(fd))
+ sock = sock_find_from_fd(fd);
+ if (sock && !SOCK_IS_CHECK_IO(sock->flags))
return 0;
timeout.tv_sec = io_timeout;
@@ -679,15 +692,27 @@ struct hostent *my_gethostbyname(const gchar *hostname)
static void sock_set_buffer_size(gint sock)
{
#ifdef G_OS_WIN32
- gint val = 32768;
+ gint val;
guint len = sizeof(val);
- setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char *)&val, len);
- setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char *)&val, len);
+#define SOCK_BUFFSIZE 32768
+
+ getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char *)&val, &len);
+ if (val < SOCK_BUFFSIZE) {
+ val = SOCK_BUFFSIZE;
+ setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char *)&val, len);
+ }
+ getsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char *)&val, &len);
+ if (val < SOCK_BUFFSIZE) {
+ val = SOCK_BUFFSIZE;
+ setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char *)&val, len);
+ }
getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char *)&val, &len);
debug_print("SO_SNDBUF = %d\n", val);
getsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char *)&val, &len);
debug_print("SO_RCVBUF = %d\n", val);
+
+#undef SOCK_BUFFSIZE
#endif
}
@@ -839,7 +864,7 @@ SockInfo *sock_connect(const gchar *hostname, gushort port)
sockinfo->hostname = g_strdup(hostname);
sockinfo->port = port;
sockinfo->state = CONN_ESTABLISHED;
- sockinfo->nonblock = FALSE;
+ sockinfo->flags = SOCK_CHECK_IO;
sock_list = g_list_prepend(sock_list, sockinfo);
@@ -899,7 +924,7 @@ static gboolean sock_connect_async_cb(GIOChannel *source,
sockinfo->hostname = g_strdup(conn_data->hostname);
sockinfo->port = conn_data->port;
sockinfo->state = CONN_ESTABLISHED;
- sockinfo->nonblock = TRUE;
+ sockinfo->flags = SOCK_NONBLOCK;
sock_list = g_list_prepend(sock_list, sockinfo);
diff --git a/libsylph/socket.h b/libsylph/socket.h
index aaa6b895..384f61a4 100644
--- a/libsylph/socket.h
+++ b/libsylph/socket.h
@@ -1,6 +1,6 @@
/*
* LibSylph -- E-Mail client library
- * Copyright (C) 1999-2006 Hiroyuki Yamamoto
+ * Copyright (C) 1999-2007 Hiroyuki Yamamoto
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -44,6 +44,17 @@ typedef enum
CONN_FAILED
} ConnectionState;
+typedef enum
+{
+ SOCK_NONBLOCK = 1 << 0,
+ SOCK_CHECK_IO = 1 << 1
+} SockFlags;
+
+#define SOCK_SET_FLAGS(flags, set) { (flags) |= (set); }
+#define SOCK_UNSET_FLAGS(flags, set) { (flags) &= ~(set); }
+#define SOCK_IS_NONBLOCK(flags) ((flags & SOCK_NONBLOCK) != 0)
+#define SOCK_IS_CHECK_IO(flags) ((flags & SOCK_CHECK_IO) != 0)
+
typedef gint (*SockConnectFunc) (SockInfo *sock,
gpointer data);
typedef gboolean (*SockFunc) (SockInfo *sock,
@@ -63,7 +74,7 @@ struct _SockInfo
gchar *hostname;
gushort port;
ConnectionState state;
- gboolean nonblock;
+ SockFlags flags;
gpointer data;
SockFunc callback;