You can try applying a loader shim that intercepts the call to socket()
and does a setsockopt()
to change the buffer size before returning to the caller. Presumably you would apply this to the java interpreter running the application, assuming it doesn't set up any weird intercepts of its own. I tested the following C on a C program and it seemed to work. See man ld.so
.
/*
* capture calls to a routine and replace with your code
* gcc -Wall -O2 -fpic -shared -ldl -o shim_socket.so shim_socket.c
* LD_PRELOAD=./shim_socket.so SO_SNDBUF=5000 ./test
* after call to socket() do SO_SNDBUF on it before return
*/
#define _GNU_SOURCE /* needed to get RTLD_NEXT defined in dlfcn.h */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <dlfcn.h>
#include <sys/types.h>
#include <sys/socket.h>
int socket(int domain, int type, int protocol){
static int (*real_socket)(int domain, int type, int protocol) = NULL;
static int newsize = 0;
int sock;
if (!real_socket) {
real_socket = dlsym(RTLD_NEXT, "socket");
char *error = dlerror();
if (error != NULL) {
fprintf(stderr, "%s\n", error);
exit(1);
}
char *sndbufsize = getenv("SO_SNDBUF");
if(sndbufsize!=0){
char *endptr;
newsize = (int)strtol(sndbufsize,&endptr,0);
if(*endptr!='\0'){
fprintf(stderr, "env SO_SNDBUF=was not int\n");
exit(2);
}
}
}
sock = real_socket(domain, type, protocol);
if(newsize){
int rc = setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &newsize, sizeof(newsize));
fprintf(stderr, "socket SO_SNDBUF=%d rc=%d\n", newsize, rc);
}
return sock;
}
Compile and run this as shown in the comment. It looks in the environment for a SO_SNDBUF=9999
value to apply after all calls to socket()
. You may want to restrict it to just some socket calls. The fprintf()
output is just for testing and may not even appear with java. Remove as appropriate. If your application runs other programs they may inherit the LD_PRELOAD
.
Note, the application may actually go on to call setsockopt()
itself, changing the size back to a smaller value. You should check with something like strace -f -e setsockopt -o outputlog
. If it does this, you can instead use a shim that intercepts this call instead of socket()
.
Also, the maximum buffer size is set globally to the value in /proc/sys/net/core/wmem_max
. You can change this, as only processes that need more buffer space will use it. Normally, the Linux kernel automatically regulates the amount of buffering needed by a process; setting SO_SNDBUF
disables this mechanism.