Re: ORBit writev screwedness ...



Hi,

> > 	This may well be down to the IOVEC limit on many unix's being much much
> > lower than on Linux;
> > 
> > 	See bugzilla.gnome.org 56270 for 1 attempt at a fix which I must
> > confess doesn't impress me.
>
> While we're at it:
> 
> I once coded a 'right' solution for IOV_MAX for ORBit-mt, but never got
> around to actually post it here for general use.
> 
> As is little known, linux does not support very long IOV_MAX (up until
> 2.0 only 16 was supported, from 2.2 on 1024), but glibc just does the
> natural thing, once the kernel calls fails. It just concatenates all
> buffers into a stack buffer and calls write. Thus the configure.in test
> didn't notice, that only 1024 (or 16) io_vecs are supported. 
> 
> So this might (and did for multi threaded CORBA applications, as they
> have limited stack-size per thread) lead to a segmentation fault and a
> crash.
> 
> So I programmed the following code-snippet, which will lead to better
> results than the configure.in test:

As there was no reaction, I figured to make a patch myself. It is
attached against CVS HEAD linc. It should really be included and might
also benefit ORBit-stable.

Bye,
Sebastian
-- 
Sebastian Wilhelmi
mailto:wilhelmi@ira.uka.de
http://goethe.ira.uka.de/~wilhelmi

Index: acconfig.h
===================================================================
RCS file: /cvs/gnome/linc/acconfig.h,v
retrieving revision 1.4
diff -p -u -b -B -r1.4 acconfig.h
--- acconfig.h	2001/10/24 06:20:42	1.4
+++ acconfig.h	2002/02/05 12:09:56
@@ -10,5 +10,4 @@
  *                 Sun Microsystems, Inc.
  */
 #undef socklen_t
-#undef WRITEV_IOVEC_LIMIT
 #undef HAVE_SOCKADDR_SA_LEN
Index: configure.in
===================================================================
RCS file: /cvs/gnome/linc/configure.in,v
retrieving revision 1.52
diff -p -u -b -B -r1.52 configure.in
--- configure.in	2002/01/28 17:27:36	1.52
+++ configure.in	2002/02/05 12:09:56
@@ -122,44 +122,6 @@ fi
 
 AC_C_BIGENDIAN
 
-AC_MSG_CHECKING(maximum number of iovecs for a writev)
-AC_TRY_RUN([
-#include <fcntl.h>
-#include <sys/uio.h>
-#include <stdio.h>
-#include <unistd.h>
-#define NIOVECS 2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2
-int main(int argc, char *argv[])
-{
-	char dumbuf[20] = "\n";
-	struct iovec iovecs[NIOVECS];
-	int i,fd;
-	FILE *f;
-
-	for(i = 0; i < NIOVECS; i++) {
-		iovecs[i].iov_base = dumbuf;
-		iovecs[i].iov_len = 1;
-	}
-
-	f = fopen("conftestval", "w");
-	fd=open("/dev/null", O_WRONLY);
-	if(fd==-1)
-		return(1);
-
-	for(i = 1; 2*i < NIOVECS; i *= 2)
-		if(writev(fd, iovecs, 2*i) < 0)
-			break;
-	fprintf(f, "%d\n", i);
-
-	close(fd);
-	fclose(f);
-	return 0;
-}
-], WRITEV_IOVEC_LIMIT="`cat conftestval`", WRITEV_IOVEC_LIMIT=1024, WRITEV_IOVEC_LIMIT=1024)
-
-AC_MSG_RESULT($WRITEV_IOVEC_LIMIT)
-AC_DEFINE_UNQUOTED(WRITEV_IOVEC_LIMIT, $WRITEV_IOVEC_LIMIT)
-
 if test "x$GCC" = "xyes" -a "x$enable_compile_warnings" != "xno"; then
 	WARN_CFLAGS="-Wall -Wunused -Wmissing-prototypes -Wmissing-declarations"
 else
Index: src/linc-connection.c
===================================================================
RCS file: /cvs/gnome/linc/src/linc-connection.c,v
retrieving revision 1.61
diff -p -u -b -B -r1.61 linc-connection.c
--- src/linc-connection.c	2002/01/21 16:24:03	1.61
+++ src/linc-connection.c	2002/02/05 12:09:57
@@ -478,6 +478,46 @@ linc_connection_read (LINCConnection *cn
 	return bytes_read;
 }
 
+/* Determine the maximum size of the iovec vector */
+
+#if defined (UIO_MAXIOV) /* Glibc */
+# define LINC_IOV_MAX (UIO_MAXIOV)
+#elif defined (MAXIOV) /* HPUX */
+# define LINC_IOV_MAX (MAXIOV)
+#elif defined (IOV_MAX) /* AIX */
+# define LINC_IOV_MAX (IOV_MAX)
+#elif defined (_SC_IOV_MAX) /* SGI */
+# define LINC_IOV_MAX_INIT (sysconf (_SC_IOV_MAX))
+#else /* Safe Guess */
+# define LINC_IOV_MAX 16
+#endif
+
+/* If the value requires initialization, define the function here */
+#if defined (LINC_IOV_MAX_INIT)
+# define LINC_IOV_MAX linc_iov_max
+  static guint linc_iov_max = 0;
+  static inline void
+  linc_iov_max_init () 
+  {
+    if (linc_iov_max == 0)
+      {
+        gint max;
+        G_LOCK_DEFINE_STATIC (linc_iov_max);
+        G_LOCK (linc_iov_max);
+        if (linc_iov_max == 0)
+          {
+            max = LINC_IOV_MAX_INIT;
+            if (max <= 0)
+              max = 16;
+            linc_iov_max = max;
+          }
+        G_UNLOCK (linc_iov_max);
+      }
+  }
+#else
+# define linc_iov_max_init()
+#endif
+
 static glong
 write_data (LINCConnection *cnx, QueuedWrite *qw)
 {
@@ -486,6 +526,8 @@ write_data (LINCConnection *cnx, QueuedW
 	g_return_val_if_fail (cnx->status == LINC_CONNECTED,
 			      LINC_IO_FATAL_ERROR);
 
+	linc_iov_max_init ();
+
 	while ((qw->nvecs > 0) && (qw->vecs->iov_len > 0)) {
 		int n;
 
@@ -499,7 +541,7 @@ write_data (LINCConnection *cnx, QueuedW
 		else
 #endif
 			n = writev (cnx->priv->fd, qw->vecs,
-				    MIN (qw->nvecs, WRITEV_IOVEC_LIMIT));
+				    MIN (qw->nvecs, LINC_IOV_MAX));
 
 		d_printf ("wrote %d bytes\n", n);
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]