Blame SOURCES/0001-configurable-maximum-number-of-clients.patch

82b592
From 3f48fe3c668a0fc420db97b3d116b5b007909876 Mon Sep 17 00:00:00 2001
82b592
From: Olivier Fourdan <ofourdan@redhat.com>
82b592
Date: Tue, 7 Jul 2015 18:19:50 +0200
82b592
Subject: [PATCH] configurable maximum number of clients
82b592
82b592
Make the maximum number of clients user configurable, either from the command
82b592
line or from xorg.conf
82b592
82b592
This patch works by using the MAXCLIENTS (raised to 512) as the maximum
82b592
allowed number of clients, but allowing the actual limit to be set by the
82b592
user to a lower value (keeping the default of 256).
82b592
82b592
There is a limit size of 29 bits to be used to store both the client ID and
82b592
the X resources ID, so by reducing the number of clients allowed to connect to
82b592
the X server, the user can increase the number of X resources per client or
82b592
vice-versa.
82b592
82b592
Parts of this patch are based on a similar patch from Adam Jackson
82b592
<ajax@redhat.com>
82b592
82b592
This now requires at least xproto 7.0.28
82b592
82b592
Signed-off-by: Adam Jackson <ajax@redhat.com>
82b592
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
82b592
Reviewed-by: Adam Jackson <ajax@redhat.com>
82b592
Signed-off-by: Keith Packard <keithp@keithp.com>
82b592
---
82b592
 dix/colormap.c                 |   28 ++++++++++++++--------------
82b592
 dix/dispatch.c                 |    4 ++--
82b592
 dix/main.c                     |    2 +-
82b592
 dix/resource.c                 |   33 ++++++++++++++++++++++++++++-----
82b592
 hw/dmx/glxProxy/glxext.c       |    2 +-
82b592
 hw/xfree86/common/xf86Config.c |   16 ++++++++++++++++
82b592
 hw/xfree86/man/xorg.conf.man   |    4 ++++
82b592
 include/misc.h                 |    3 ++-
82b592
 include/opaque.h               |    1 +
82b592
 include/resource.h             |   15 ++-------------
82b592
 man/Xserver.man                |    5 +++++
82b592
 os/connection.c                |    6 +++---
82b592
 os/osdep.h                     |    8 ++++----
82b592
 os/osinit.c                    |    3 +++
82b592
 os/utils.c                     |   14 ++++++++++++++
82b592
 15 files changed, 100 insertions(+), 44 deletions(-)
82b592
82b592
diff --git a/dix/colormap.c b/dix/colormap.c
82b592
index 4d408d5..ac1a615 100644
82b592
--- a/dix/colormap.c
82b592
+++ b/dix/colormap.c
82b592
@@ -249,7 +249,7 @@ CreateColormap(Colormap mid, ScreenPtr pScreen, VisualPtr pVisual,
82b592
 
82b592
     size = pVisual->ColormapEntries;
82b592
     sizebytes = (size * sizeof(Entry)) +
82b592
-        (MAXCLIENTS * sizeof(Pixel *)) + (MAXCLIENTS * sizeof(int));
82b592
+        (LimitClients * sizeof(Pixel *)) + (LimitClients * sizeof(int));
82b592
     if ((class | DynamicClass) == DirectColor)
82b592
         sizebytes *= 3;
82b592
     sizebytes += sizeof(ColormapRec);
82b592
@@ -274,7 +274,7 @@ CreateColormap(Colormap mid, ScreenPtr pScreen, VisualPtr pVisual,
82b592
     sizebytes = size * sizeof(Entry);
82b592
     pmap->clientPixelsRed = (Pixel **) ((char *) pmap->red + sizebytes);
82b592
     pmap->numPixelsRed = (int *) ((char *) pmap->clientPixelsRed +
82b592
-                                  (MAXCLIENTS * sizeof(Pixel *)));
82b592
+                                  (LimitClients * sizeof(Pixel *)));
82b592
     pmap->mid = mid;
82b592
     pmap->flags = 0;            /* start out with all flags clear */
82b592
     if (mid == pScreen->defColormap)
82b592
@@ -286,8 +286,8 @@ CreateColormap(Colormap mid, ScreenPtr pScreen, VisualPtr pVisual,
82b592
         size = NUMRED(pVisual);
82b592
     pmap->freeRed = size;
82b592
     memset((char *) pmap->red, 0, (int) sizebytes);
82b592
-    memset((char *) pmap->numPixelsRed, 0, MAXCLIENTS * sizeof(int));
82b592
-    for (pptr = &pmap->clientPixelsRed[MAXCLIENTS];
82b592
+    memset((char *) pmap->numPixelsRed, 0, LimitClients * sizeof(int));
82b592
+    for (pptr = &pmap->clientPixelsRed[LimitClients];
82b592
          --pptr >= pmap->clientPixelsRed;)
82b592
         *pptr = (Pixel *) NULL;
82b592
     if (alloc == AllocAll) {
82b592
@@ -310,26 +310,26 @@ CreateColormap(Colormap mid, ScreenPtr pScreen, VisualPtr pVisual,
82b592
     if ((class | DynamicClass) == DirectColor) {
82b592
         pmap->freeGreen = NUMGREEN(pVisual);
82b592
         pmap->green = (EntryPtr) ((char *) pmap->numPixelsRed +
82b592
-                                  (MAXCLIENTS * sizeof(int)));
82b592
+                                  (LimitClients * sizeof(int)));
82b592
         pmap->clientPixelsGreen = (Pixel **) ((char *) pmap->green + sizebytes);
82b592
         pmap->numPixelsGreen = (int *) ((char *) pmap->clientPixelsGreen +
82b592
-                                        (MAXCLIENTS * sizeof(Pixel *)));
82b592
+                                        (LimitClients * sizeof(Pixel *)));
82b592
         pmap->freeBlue = NUMBLUE(pVisual);
82b592
         pmap->blue = (EntryPtr) ((char *) pmap->numPixelsGreen +
82b592
-                                 (MAXCLIENTS * sizeof(int)));
82b592
+                                 (LimitClients * sizeof(int)));
82b592
         pmap->clientPixelsBlue = (Pixel **) ((char *) pmap->blue + sizebytes);
82b592
         pmap->numPixelsBlue = (int *) ((char *) pmap->clientPixelsBlue +
82b592
-                                       (MAXCLIENTS * sizeof(Pixel *)));
82b592
+                                       (LimitClients * sizeof(Pixel *)));
82b592
 
82b592
         memset((char *) pmap->green, 0, (int) sizebytes);
82b592
         memset((char *) pmap->blue, 0, (int) sizebytes);
82b592
 
82b592
         memmove((char *) pmap->clientPixelsGreen,
82b592
-                (char *) pmap->clientPixelsRed, MAXCLIENTS * sizeof(Pixel *));
82b592
+                (char *) pmap->clientPixelsRed, LimitClients * sizeof(Pixel *));
82b592
         memmove((char *) pmap->clientPixelsBlue,
82b592
-                (char *) pmap->clientPixelsRed, MAXCLIENTS * sizeof(Pixel *));
82b592
-        memset((char *) pmap->numPixelsGreen, 0, MAXCLIENTS * sizeof(int));
82b592
-        memset((char *) pmap->numPixelsBlue, 0, MAXCLIENTS * sizeof(int));
82b592
+                (char *) pmap->clientPixelsRed, LimitClients * sizeof(Pixel *));
82b592
+        memset((char *) pmap->numPixelsGreen, 0, LimitClients * sizeof(int));
82b592
+        memset((char *) pmap->numPixelsBlue, 0, LimitClients * sizeof(int));
82b592
 
82b592
         /* If every cell is allocated, mark its refcnt */
82b592
         if (alloc == AllocAll) {
82b592
@@ -413,7 +413,7 @@ FreeColormap(void *value, XID mid)
82b592
     (*pmap->pScreen->DestroyColormap) (pmap);
82b592
 
82b592
     if (pmap->clientPixelsRed) {
82b592
-        for (i = 0; i < MAXCLIENTS; i++)
82b592
+        for (i = 0; i < LimitClients; i++)
82b592
             free(pmap->clientPixelsRed[i]);
82b592
     }
82b592
 
82b592
@@ -431,7 +431,7 @@ FreeColormap(void *value, XID mid)
82b592
         }
82b592
     }
82b592
     if ((pmap->class | DynamicClass) == DirectColor) {
82b592
-        for (i = 0; i < MAXCLIENTS; i++) {
82b592
+        for (i = 0; i < LimitClients; i++) {
82b592
             free(pmap->clientPixelsGreen[i]);
82b592
             free(pmap->clientPixelsBlue[i]);
82b592
         }
82b592
diff --git a/dix/dispatch.c b/dix/dispatch.c
82b592
index 17fa75e..bb4a110 100644
82b592
--- a/dix/dispatch.c
82b592
+++ b/dix/dispatch.c
82b592
@@ -3483,7 +3483,7 @@ NextAvailableClient(void *ospriv)
82b592
     xReq data;
82b592
 
82b592
     i = nextFreeClientID;
82b592
-    if (i == MAXCLIENTS)
82b592
+    if (i == LimitClients)
82b592
         return (ClientPtr) NULL;
82b592
     clients[i] = client =
82b592
         dixAllocateObjectWithPrivates(ClientRec, PRIVATE_CLIENT);
82b592
@@ -3503,7 +3503,7 @@ NextAvailableClient(void *ospriv)
82b592
     }
82b592
     if (i == currentMaxClients)
82b592
         currentMaxClients++;
82b592
-    while ((nextFreeClientID < MAXCLIENTS) && clients[nextFreeClientID])
82b592
+    while ((nextFreeClientID < LimitClients) && clients[nextFreeClientID])
82b592
         nextFreeClientID++;
82b592
 
82b592
     /* Enable client ID tracking. This must be done before
82b592
diff --git a/dix/main.c b/dix/main.c
82b592
index 7c6ac94..287a335 100644
82b592
--- a/dix/main.c
82b592
+++ b/dix/main.c
82b592
@@ -163,7 +163,7 @@ dix_main(int argc, char *argv[], char *envp[])
82b592
         OsInit();
82b592
         if (serverGeneration == 1) {
82b592
             CreateWellKnownSockets();
82b592
-            for (i = 1; i < MAXCLIENTS; i++)
82b592
+            for (i = 1; i < LimitClients; i++)
82b592
                 clients[i] = NullClient;
82b592
             serverClient = calloc(sizeof(ClientRec), 1);
82b592
             if (!serverClient)
82b592
diff --git a/dix/resource.c b/dix/resource.c
82b592
index 964f0b3..b33d959 100644
82b592
--- a/dix/resource.c
82b592
+++ b/dix/resource.c
82b592
@@ -600,6 +600,29 @@ CreateNewResourceClass(void)
82b592
 
82b592
 static ClientResourceRec clientTable[MAXCLIENTS];
82b592
 
82b592
+static unsigned int
82b592
+ilog2(int val)
82b592
+{
82b592
+    int bits;
82b592
+
82b592
+    if (val <= 0)
82b592
+	return 0;
82b592
+    for (bits = 0; val != 0; bits++)
82b592
+	val >>= 1;
82b592
+    return bits - 1;
82b592
+}
82b592
+
82b592
+/*****************
82b592
+ * ResourceClientBits
82b592
+ *    Returns the client bit offset in the client + resources ID field
82b592
+ *****************/
82b592
+
82b592
+unsigned int
82b592
+ResourceClientBits(void)
82b592
+{
82b592
+    return (ilog2(LimitClients));
82b592
+}
82b592
+
82b592
 /*****************
82b592
  * InitClientResources
82b592
  *    When a new client is created, call this to allocate space
82b592
@@ -883,7 +906,7 @@ FreeResource(XID id, RESTYPE skipDeleteFuncType)
82b592
     int *eltptr;
82b592
     int elements;
82b592
 
82b592
-    if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets) {
82b592
+    if (((cid = CLIENT_ID(id)) < LimitClients) && clientTable[cid].buckets) {
82b592
         head = &clientTable[cid].resources[HashResourceID(id, clientTable[cid].hashsize)];
82b592
         eltptr = &clientTable[cid].elements;
82b592
 
82b592
@@ -917,7 +940,7 @@ FreeResourceByType(XID id, RESTYPE type, Bool skipFree)
82b592
     ResourcePtr res;
82b592
     ResourcePtr *prev, *head;
82b592
 
82b592
-    if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets) {
82b592
+    if (((cid = CLIENT_ID(id)) < LimitClients) && clientTable[cid].buckets) {
82b592
         head = &clientTable[cid].resources[HashResourceID(id, clientTable[cid].hashsize)];
82b592
 
82b592
         prev = head;
82b592
@@ -952,7 +975,7 @@ ChangeResourceValue(XID id, RESTYPE rtype, void *value)
82b592
     int cid;
82b592
     ResourcePtr res;
82b592
 
82b592
-    if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets) {
82b592
+    if (((cid = CLIENT_ID(id)) < LimitClients) && clientTable[cid].buckets) {
82b592
         res = clientTable[cid].resources[HashResourceID(id, clientTable[cid].hashsize)];
82b592
 
82b592
         for (; res; res = res->next)
82b592
@@ -1190,7 +1213,7 @@ dixLookupResourceByType(void **result, XID id, RESTYPE rtype,
82b592
     if ((rtype & TypeMask) > lastResourceType)
82b592
         return BadImplementation;
82b592
 
82b592
-    if ((cid < MAXCLIENTS) && clientTable[cid].buckets) {
82b592
+    if ((cid < LimitClients) && clientTable[cid].buckets) {
82b592
         res = clientTable[cid].resources[HashResourceID(id, clientTable[cid].hashsize)];
82b592
 
82b592
         for (; res; res = res->next)
82b592
@@ -1223,7 +1246,7 @@ dixLookupResourceByClass(void **result, XID id, RESTYPE rclass,
82b592
 
82b592
     *result = NULL;
82b592
 
82b592
-    if ((cid < MAXCLIENTS) && clientTable[cid].buckets) {
82b592
+    if ((cid < LimitClients) && clientTable[cid].buckets) {
82b592
         res = clientTable[cid].resources[HashResourceID(id, clientTable[cid].hashsize)];
82b592
 
82b592
         for (; res; res = res->next)
82b592
diff --git a/hw/dmx/glxProxy/glxext.c b/hw/dmx/glxProxy/glxext.c
82b592
index 3c5a14b..c858272 100644
82b592
--- a/hw/dmx/glxProxy/glxext.c
82b592
+++ b/hw/dmx/glxProxy/glxext.c
82b592
@@ -347,7 +347,7 @@ GlxExtensionInit(void)
82b592
     /*
82b592
      ** Initialize table of client state.  There is never a client 0.
82b592
      */
82b592
-    for (i = 1; i <= MAXCLIENTS; i++) {
82b592
+    for (i = 1; i <= LimitClients; i++) {
82b592
         __glXClients[i] = 0;
82b592
     }
82b592
 
82b592
diff --git a/hw/xfree86/common/xf86Config.c b/hw/xfree86/common/xf86Config.c
82b592
index d42572f..5f7d13b 100644
82b592
--- a/hw/xfree86/common/xf86Config.c
82b592
+++ b/hw/xfree86/common/xf86Config.c
82b592
@@ -697,6 +697,7 @@ typedef enum {
82b592
     FLAG_DRI2,
82b592
     FLAG_USE_SIGIO,
82b592
     FLAG_AUTO_ADD_GPU,
82b592
+    FLAG_MAX_CLIENTS,
82b592
 } FlagValues;
82b592
 
82b592
 /**
82b592
@@ -756,6 +757,8 @@ static OptionInfoRec FlagOptions[] = {
82b592
      {0}, FALSE},
82b592
     {FLAG_AUTO_ADD_GPU, "AutoAddGPU", OPTV_BOOLEAN,
82b592
      {0}, FALSE},
82b592
+    {FLAG_MAX_CLIENTS, "MaxClients", OPTV_INTEGER,
82b592
+     {0}, FALSE },
82b592
     {-1, NULL, OPTV_NONE,
82b592
      {0}, FALSE},
82b592
 };
82b592
@@ -1046,6 +1049,19 @@ configServerFlags(XF86ConfFlagsPtr flagsconf, XF86OptionPtr layoutopts)
82b592
         xf86Info.dri2From = X_CONFIG;
82b592
     }
82b592
 #endif
82b592
+
82b592
+    from = X_DEFAULT;
82b592
+    if (LimitClients != LIMITCLIENTS)
82b592
+	from = X_CMDLINE;
82b592
+    i = -1;
82b592
+    if (xf86GetOptValInteger(FlagOptions, FLAG_MAX_CLIENTS, &i)) {
82b592
+	if (i != 64 && i != 128 && i != 256 && i != 512)
82b592
+		ErrorF("MaxClients must be one of 64, 128, 256 or 512\n");
82b592
+	from = X_CONFIG;
82b592
+	LimitClients = i;
82b592
+    }
82b592
+    xf86Msg(from, "Max clients allowed: %i, resource mask: 0x%x\n",
82b592
+	    LimitClients, RESOURCE_ID_MASK);
82b592
 }
82b592
 
82b592
 Bool
82b592
diff --git a/hw/xfree86/man/xorg.conf.man b/hw/xfree86/man/xorg.conf.man
82b592
index d26c3cc..9157fc9 100644
82b592
--- a/hw/xfree86/man/xorg.conf.man
82b592
+++ b/hw/xfree86/man/xorg.conf.man
82b592
@@ -621,6 +621,10 @@ It is only enabled for screens that have the
82b592
 .B \*qDPMS\*q
82b592
 option set (see the MONITOR section below).
82b592
 .TP 7
82b592
+.BI "Option \*qMaxClients\*q  \*q" integer \*q
82b592
+Set the maximum number of clients allowed to connect to the X server.
82b592
+Acceptable values are 64, 128, 256 or 512.
82b592
+.TP 7
82b592
 .BI "Option \*qPixmap\*q  \*q" bpp \*q
82b592
 This sets the pixmap format to use for depth 24.
82b592
 Allowed values for
82b592
diff --git a/include/misc.h b/include/misc.h
82b592
index 9b1c03a..56e138c 100644
82b592
--- a/include/misc.h
82b592
+++ b/include/misc.h
82b592
@@ -86,7 +86,8 @@ OF THIS SOFTWARE.
82b592
 #ifndef MAXGPUSCREENS
82b592
 #define MAXGPUSCREENS	16
82b592
 #endif
82b592
-#define MAXCLIENTS	256
82b592
+#define MAXCLIENTS	512
82b592
+#define LIMITCLIENTS	256     /* Must be a power of 2 and <= MAXCLIENTS */
82b592
 #define MAXEXTENSIONS   128
82b592
 #define MAXFORMATS	8
82b592
 #define MAXDEVICES	40      /* input devices */
82b592
diff --git a/include/opaque.h b/include/opaque.h
82b592
index a2c54aa..0ba0d64 100644
82b592
--- a/include/opaque.h
82b592
+++ b/include/opaque.h
82b592
@@ -36,6 +36,7 @@ from The Open Group.
82b592
 extern _X_EXPORT const char *defaultTextFont;
82b592
 extern _X_EXPORT const char *defaultCursorFont;
82b592
 extern _X_EXPORT int MaxClients;
82b592
+extern _X_EXPORT int LimitClients;
82b592
 extern _X_EXPORT volatile char isItTimeToYield;
82b592
 extern _X_EXPORT volatile char dispatchException;
82b592
 
82b592
diff --git a/include/resource.h b/include/resource.h
82b592
index 772f363..597f7b6 100644
82b592
--- a/include/resource.h
82b592
+++ b/include/resource.h
82b592
@@ -85,21 +85,10 @@ typedef uint32_t RESTYPE;
82b592
 #define RT_LASTPREDEF	((RESTYPE)9)
82b592
 #define RT_NONE		((RESTYPE)0)
82b592
 
82b592
+extern unsigned int ResourceClientBits(void);
82b592
 /* bits and fields within a resource id */
82b592
 #define RESOURCE_AND_CLIENT_COUNT   29  /* 29 bits for XIDs */
82b592
-#if MAXCLIENTS == 64
82b592
-#define RESOURCE_CLIENT_BITS	6
82b592
-#endif
82b592
-#if MAXCLIENTS == 128
82b592
-#define RESOURCE_CLIENT_BITS	7
82b592
-#endif
82b592
-#if MAXCLIENTS == 256
82b592
-#define RESOURCE_CLIENT_BITS	8
82b592
-#endif
82b592
-#if MAXCLIENTS == 512
82b592
-#define RESOURCE_CLIENT_BITS	9
82b592
-#endif
82b592
-/* client field offset */
82b592
+#define RESOURCE_CLIENT_BITS        ResourceClientBits() /* client field offset */
82b592
 #define CLIENTOFFSET	    (RESOURCE_AND_CLIENT_COUNT - RESOURCE_CLIENT_BITS)
82b592
 /* resource field */
82b592
 #define RESOURCE_ID_MASK	((1 << CLIENTOFFSET) - 1)
82b592
diff --git a/man/Xserver.man b/man/Xserver.man
82b592
index bc4c7fc..d927913 100644
82b592
--- a/man/Xserver.man
82b592
+++ b/man/Xserver.man
82b592
@@ -320,6 +320,11 @@ sets the stack space limit of the server to the specified number of kilobytes.
82b592
 A value of zero makes the stack size as large as possible.  The default value
82b592
 of \-1 leaves the stack space limit unchanged.
82b592
 .TP 8
82b592
+.B \-maxclients
82b592
+.BR 64 | 128 | 256 | 512
82b592
+Set the maximum number of clients allowed to connect to the X server.
82b592
+Acceptable values are 64, 128, 256 or 512.
82b592
+.TP 8
82b592
 .B \-render
82b592
 .BR default | mono | gray | color
82b592
 sets the color allocation policy that will be used by the render extension.
82b592
diff --git a/os/connection.c b/os/connection.c
82b592
index 7ff44e1..d198e1f 100644
82b592
--- a/os/connection.c
82b592
+++ b/os/connection.c
82b592
@@ -161,9 +161,9 @@ int *ConnectionTranslation = NULL;
82b592
  */
82b592
 
82b592
 #undef MAXSOCKS
82b592
-#define MAXSOCKS 500
82b592
+#define MAXSOCKS 512
82b592
 #undef MAXSELECT
82b592
-#define MAXSELECT 500
82b592
+#define MAXSELECT 512
82b592
 
82b592
 struct _ct_node {
82b592
     struct _ct_node *next;
82b592
@@ -299,7 +299,7 @@ InitConnectionLimits(void)
82b592
     if (lastfdesc > MAXCLIENTS) {
82b592
         lastfdesc = MAXCLIENTS;
82b592
         if (debug_conns)
82b592
-            ErrorF("REACHED MAXIMUM CLIENTS LIMIT %d\n", MAXCLIENTS);
82b592
+            ErrorF("REACHED MAXIMUM CLIENTS LIMIT %d\n", LimitClients);
82b592
     }
82b592
     MaxClients = lastfdesc;
82b592
 
82b592
diff --git a/os/osdep.h b/os/osdep.h
82b592
index 77a5b53..86263a5 100644
82b592
--- a/os/osdep.h
82b592
+++ b/os/osdep.h
82b592
@@ -65,7 +65,7 @@ SOFTWARE.
82b592
 
82b592
 #ifndef OPEN_MAX
82b592
 #ifdef SVR4
82b592
-#define OPEN_MAX 256
82b592
+#define OPEN_MAX 512
82b592
 #else
82b592
 #include <sys/param.h>
82b592
 #ifndef OPEN_MAX
82b592
@@ -75,7 +75,7 @@ SOFTWARE.
82b592
 #if !defined(WIN32)
82b592
 #define OPEN_MAX NOFILES_MAX
82b592
 #else
82b592
-#define OPEN_MAX 256
82b592
+#define OPEN_MAX 512
82b592
 #endif
82b592
 #endif
82b592
 #endif
82b592
@@ -89,10 +89,10 @@ SOFTWARE.
82b592
  * like sysconf(_SC_OPEN_MAX) is not supported.
82b592
  */
82b592
 
82b592
-#if OPEN_MAX <= 256
82b592
+#if OPEN_MAX <= 512
82b592
 #define MAXSOCKS (OPEN_MAX - 1)
82b592
 #else
82b592
-#define MAXSOCKS 256
82b592
+#define MAXSOCKS 512
82b592
 #endif
82b592
 
82b592
 /* MAXSELECT is the number of fds that select() can handle */
82b592
diff --git a/os/osinit.c b/os/osinit.c
82b592
index 91e3e06..ddd3fce 100644
82b592
--- a/os/osinit.c
82b592
+++ b/os/osinit.c
82b592
@@ -86,6 +86,9 @@ int limitStackSpace = -1;
82b592
 int limitNoFile = -1;
82b592
 #endif
82b592
 
82b592
+/* The actual user defined max number of clients */
82b592
+int LimitClients = LIMITCLIENTS;
82b592
+
82b592
 static OsSigWrapperPtr OsSigWrapper = NULL;
82b592
 
82b592
 OsSigWrapperPtr
82b592
diff --git a/os/utils.c b/os/utils.c
82b592
index 03721fd..b518add 100644
82b592
--- a/os/utils.c
82b592
+++ b/os/utils.c
82b592
@@ -556,6 +556,7 @@ UseMsg(void)
82b592
 #ifdef LOCK_SERVER
82b592
     ErrorF("-nolock                disable the locking mechanism\n");
82b592
 #endif
82b592
+    ErrorF("-maxclients n          set maximum number of clients (power of two)\n");
82b592
     ErrorF("-nolisten string       don't listen on protocol\n");
82b592
     ErrorF("-listen string         listen on protocol\n");
82b592
     ErrorF("-noreset               don't reset after last client exists\n");
82b592
@@ -860,6 +861,19 @@ ProcessCommandLine(int argc, char *argv[])
82b592
                 nolock = TRUE;
82b592
         }
82b592
 #endif
82b592
+	else if ( strcmp( argv[i], "-maxclients") == 0)
82b592
+	{
82b592
+	    if (++i < argc) {
82b592
+		LimitClients = atoi(argv[i]);
82b592
+		if (LimitClients != 64 &&
82b592
+		    LimitClients != 128 &&
82b592
+		    LimitClients != 256 &&
82b592
+		    LimitClients != 512) {
82b592
+		    FatalError("maxclients must be one of 64, 128, 256 or 512\n");
82b592
+		}
82b592
+	    } else
82b592
+		UseMsg();
82b592
+	}
82b592
         else if (strcmp(argv[i], "-nolisten") == 0) {
82b592
             if (++i < argc) {
82b592
                 if (_XSERVTransNoListen(argv[i]))
82b592
-- 
82b592
1.7.1
82b592