Add command line option --max-connect=INT to allow the user to provide
an upper bound for the number of connected processes.
Part of fixing BZ #337869.
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@14854 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/auxprogs/valgrind-di-server.c b/auxprogs/valgrind-di-server.c
index 4a16afd..bfcdd18 100644
--- a/auxprogs/valgrind-di-server.c
+++ b/auxprogs/valgrind-di-server.c
@@ -109,8 +109,13 @@
/*---------------------------------------------------------------*/
-/* The maximum allowable number concurrent connections. */
-#define M_CONNECTIONS 50
+/* The default allowable number of concurrent connections. */
+#define M_CONNECTIONS_DEFAULT 50
+/* The maximum allowable number of concurrent connections. */
+#define M_CONNECTIONS_MAX 5000
+
+/* The maximum allowable number of concurrent connections. */
+unsigned M_CONNECTIONS = 0;
static const char* clo_serverpath = ".";
@@ -150,6 +155,20 @@
/*---------------------------------------------------------------*/
+/* Allocate some memory. Return iff successful. */
+static void *my_malloc(size_t amount)
+{
+ void *p = malloc(amount ?: 1);
+
+ if (p == NULL) {
+ fprintf(stderr, "Memory allocation failed; cannot continue.\n");
+ exit(1);
+ }
+ return p;
+}
+
+/*---------------------------------------------------------------*/
+
/* Holds the state that we need to track, for each connection. */
typedef
struct {
@@ -173,7 +192,7 @@
/* The state itself. */
static int conn_count = 0;
-static ConnState conn_state[M_CONNECTIONS];
+static ConnState *conn_state;
/* Issues unique session ID values. */
static ULong next_session_id = 1;
@@ -803,7 +822,7 @@
if (ok) {
/* First, allocate a temp buf and read from the file into it. */
/* FIXME: what if pread reads short and we have to redo it? */
- UChar* unzBuf = malloc(req_len);
+ UChar* unzBuf = my_malloc(req_len);
size_t nRead = pread(conn_state[conn_no].file_fd,
unzBuf, req_len, req_offset);
if (nRead != req_len) {
@@ -822,7 +841,7 @@
STACK_ALLOC(wrkmem, LZO1X_1_MEM_COMPRESS);
# undef STACK_ALLOC
UInt zLenMax = req_len + req_len / 4 + 1024;
- UChar* zBuf = malloc(zLenMax);
+ UChar* zBuf = my_malloc(zLenMax);
lzo_uint zLen = zLenMax;
Int lzo_rc = lzo1x_1_compress(unzBuf, req_len,
zBuf, &zLen, wrkmem);
@@ -965,8 +984,8 @@
}
-/* returns 0 if invalid, else port # */
-static int atoi_portno ( const char* str )
+/* returns 0 if negative, or > BOUND or invalid characters were found */
+static int atoi_with_bound ( const char* str, int bound )
{
int n = 0;
while (1) {
@@ -976,9 +995,18 @@
return 0;
n = 10*n + (int)(*str - '0');
str++;
- if (n >= 65536)
+ if (n >= bound)
return 0;
}
+ return n;
+}
+
+
+/* returns 0 if invalid, else port # */
+static int atoi_portno ( const char* str )
+{
+ int n = atoi_with_bound(str, 65536);
+
if (n < 1024)
return 0;
return n;
@@ -997,12 +1025,16 @@
" when the number of connections falls back to zero\n"
" (the default is to keep listening forever)\n"
"\n"
+ " --max-connect=INT can be used to increase the maximum\n"
+ " number of connected processes (default = %d).\n"
+ " INT must be positive and less than %d.\n"
+ "\n"
" port-number is the default port on which to listen for\n"
" connections. It must be between 1024 and 65535.\n"
" Current default is %d.\n"
"\n"
,
- VG_CLO_DEFAULT_LOGPORT
+ M_CONNECTIONS_DEFAULT, M_CONNECTIONS_MAX, VG_CLO_DEFAULT_LOGPORT
);
exit(1);
}
@@ -1045,6 +1077,11 @@
|| 0==strcmp(argv[i], "-e")) {
exit_when_zero = 1;
}
+ else if (0 == strncmp(argv[i], "--max-connect=", 14)) {
+ M_CONNECTIONS = atoi_with_bound(strchr(argv[i], '=') + 1, 5000);
+ if (M_CONNECTIONS <= 0 || M_CONNECTIONS > M_CONNECTIONS_MAX)
+ usage();
+ }
else
if (atoi_portno(argv[i]) > 0) {
port = atoi_portno(argv[i]);
@@ -1053,11 +1090,16 @@
usage();
}
+ if (M_CONNECTIONS == 0) // nothing specified on command line
+ M_CONNECTIONS = M_CONNECTIONS_DEFAULT;
+
+ conn_state = my_malloc(M_CONNECTIONS * sizeof conn_state[0]);
+
banner("started");
signal(SIGINT, sigint_handler);
conn_count = 0;
- memset(&conn_state, 0, sizeof(conn_state));
+ memset(conn_state, 0, M_CONNECTIONS * sizeof conn_state[0]);
/* create socket */
main_sd = socket(AF_INET, SOCK_STREAM, 0);
@@ -1128,9 +1170,11 @@
break;
if (i >= M_CONNECTIONS) {
- fprintf(stderr, "Too many concurrent connections. "
- "Increase M_CONNECTIONS and recompile.\n");
- panic("main -- too many concurrent connections");
+ fprintf(stderr, "\n\nMore than %d concurrent connections.\n"
+ "Restart the server giving --max-connect=INT on the\n"
+ "commandline to increase the limit.\n\n",
+ M_CONNECTIONS);
+ exit(1);
}
assert(one == 1);
@@ -1151,10 +1195,17 @@
/* We've processed all new connect requests. Listen for changes
to the current set of fds. This requires gathering up all
the known conn_sd values and doing poll() on them. */
- struct pollfd tmp_pollfd[M_CONNECTIONS];
+ static struct pollfd *tmp_pollfd;
+ if (tmp_pollfd == NULL)
+ tmp_pollfd = my_malloc(M_CONNECTIONS * sizeof tmp_pollfd[0]);
+
/* And a parallel array which maps entries in tmp_pollfd back to
entries in conn_state. */
- int tmp_pollfd_to_conn_state[M_CONNECTIONS];
+ static int *tmp_pollfd_to_conn_state;
+ if (tmp_pollfd_to_conn_state == NULL)
+ tmp_pollfd_to_conn_state =
+ my_malloc(M_CONNECTIONS * sizeof tmp_pollfd_to_conn_state[0]);
+
j = 0;
for (i = 0; i < M_CONNECTIONS; i++) {
if (!conn_state[i].in_use)