问题
Our application uses several socket connections (to localhost) implemented in c, with one connection using a jni/c socket connection. All of them call the same include to open the socket, and all are successful when we run the application on Solaris 10. Migrating to Solaris 11, we are finding that only the socket connections built in c are working, the one jni/c connection will not. I've added output to see what exactly is being sent to the connect call and it looks like the call is getting everything it needs:
"sock_connect: socket status: 0, sock_d: 27, serv_addr: ***.***.***.***, sizeof: 16"
So for the call below, sock_d = 27
serv_addr = (it returns a good IP, but my PM said he'd kill me if I put the actual IP)
sizeof(serv_addr) = 16
which should be all the parameters connect() needs in the code snippet below.
.
.
.
.
status = connect(sock_d, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
if (status < 0){
fprintf(stderr, "sock_connect 4: after connect errno: %i, error %sn", errno, strerror(errno));
if (errno == EINPROGRESS){
fprintf(stderr, "sock_connect, errno == EINPROGRESS\n");
.
.
.
Truss output for the failed connection seems to indicate an EINPROGRESS
error. Our code is supposed to validate for this possibility, but it does not trigger an if statement that checks to see if the error == EINPROGRESS
. It never reaches the second fprintf
statement. We have disabled IPv6 on the server, as we thought perhaps java was trying to force this protocol, but this didn't make a difference either.
The exact same libraries and executables will work on both servers, right up until the jni socket call is made. From that point on Solaris 10 keeps going but Solaris 11 will not.
Has anyone seen this before? Please let me know what else you need to see and I'll post it. Thanks in advance!
回答1:
This code incorrectly assumes fprintf()
will never modify errno
:
if (status < 0){
fprintf(stderr, "sock_connect 4: after connect errno: %i, error %sn", errno, strerror(errno));
if (errno == EINPROGRESS){
fprintf(stderr, "sock_connect, errno == EINPROGRESS\n");
The POSIX standard for errno states (emphasis mine):
The value of
errno
shall be defined only after a call to a function for which it is explicitly stated to be set and until it is changed by the next function call or if the application assigns it a value.
And per the Solaris 11.3 fprintf() man page, fprintf()
can set errno
:
Errors
For the conditions under which
printf()
,fprintf()
, anddprintf()
will fail and may fail, refer to fputc(3C) or fputwc(3C).The
snprintf()
function will fail if:EOVERFLOW
The value of n is greater than INT_MAX or the number of bytes needed to hold the output excluding the terminating null is greater than INT_MAX.
All forms of
printf()
will fail if:EILSEQ
A wide-character code that does not correspond to a valid character has been detected.
EINVAL
There are insufficient arguments.
The
dprintf()
function will fail if:EBADF
The
fildes
argument is not a valid file descriptor.The
printf()
,fprintf()
,dprintf()
, andasprintf()
functions may fail due to an underlyingmalloc(3C)
failure if:EAGAIN
Storage space is temporarily unavailable.
ENOMEM
Insufficient storage space is available.
来源:https://stackoverflow.com/questions/49701612/jni-c-socket-connection-error-on-solaris-11