diff --git a/src/coio.m b/src/coio.m
index 84ab087614c0032091c7178406873dc9354f8d9b..c1c8a2c746f40edf95c0f503f28d73bc4b0a0a27 100644
--- a/src/coio.m
+++ b/src/coio.m
@@ -201,6 +201,23 @@ coio_write(struct ev_io *coio, const void *buf, size_t sz)
 	}
 }
 
+/*
+ * Write iov using sio API.
+ * Put in an own function to workaround gcc bug with @finally
+ */
+static inline ssize_t
+coio_flush(int fd, struct iovec *iov, ssize_t offset, int iovcnt)
+{
+	ssize_t nwr;
+	@try {
+		sio_add_to_iov(iov, -offset);
+		nwr = sio_writev(fd, iov, iovcnt);
+	} @finally {
+		sio_add_to_iov(iov, offset);
+	}
+	return nwr;
+}
+
 ssize_t
 coio_writev(struct ev_io *coio, struct iovec *iov, int iovcnt, size_t size_hint)
 {
@@ -211,13 +228,8 @@ coio_writev(struct ev_io *coio, struct iovec *iov, int iovcnt, size_t size_hint)
 		/* Avoid a syscall in case of 0 iovcnt. */
 		while (iov < end) {
 			/* Write as much data as possible. */
-			ssize_t nwr;
-			@try {
-				sio_add_to_iov(iov, -iov_len);
-				nwr = sio_writev(coio->fd, iov, end - iov);
-			} @finally {
-				sio_add_to_iov(iov, iov_len);
-			}
+			ssize_t nwr = coio_flush(coio->fd, iov, iov_len,
+						 end - iov);
 			if (nwr >= 0) {
 				total += nwr;
 				/*