Zmq_getsockopt returns EINVAL on x64 windows when the local address of the ZMQ_FD option_val is passed

On x64 windows, passing a local variable address to zmq_getsockopt to ZMQ_FD sequentially results in EINVAL. The code below is the smallest possible to reproduce the problem.

#include <zmq.h>                                                                                                                                                                                                   
#include <stdio.h>                                                                                                                                                                                                 

void zmq_perror(const char*);                                                                                                                                                                                      

int main(void)                                                                                                                                                                                                     
{                                                                                                                                                                                                                  
    const char *endpoint = "tcp://127.0.0.1:7100";                                                                                                                                                                 

    void *ctx    = zmq_ctx_new();                                                                                                                                                                                  
    if (ctx == NULL) { zmq_perror("zmq_ctx_new"); }                                                                                                                                                                

    void *socket = zmq_socket(ctx, ZMQ_DEALER);                                                                                                                                                                    
    if (socket == NULL) { zmq_perror("zmq_socket"); }                                                                                                                                                              

    int rc;                                                                                                                                                                                                        

    rc = zmq_connect(socket, endpoint);                                                                                                                                                                            
    if ( rc == -1 ) { zmq_perror("zmq_connect"); }                                                                                                                                                                 


    /*** This results in EINVAL ***/                                                                                                                                                                                                               
    int fd;                                                                                                                                                                                                      
    size_t fd_size = sizeof (fd);                                                                                                                                                                                
    rc = zmq_getsockopt(socket, ZMQ_FD, &fd, &fd_size);                                                                                                                                                          
    if (rc == -1) { zmq_perror("zmq_getsockopt"); }                                                                                                                                                              


    /*** This works without issue ***/
    /*                                                                                                                                                                                                           
    int *fd        = malloc(sizeof(int));                                                                                                                                                                          
    size_t fd_size = sizeof (fd);                                                                                                                                                                                  
    rc = zmq_getsockopt(socket, ZMQ_FD, fd, &fd_size);                                                                                                                                                             
    if (rc == -1) { zmq_perror("zmq_getsockopt"); }  
    */                                                                                                                                                              
}                                                                                                                                                                                                                  

void zmq_perror(const char *f)                                                                                                                                                                                     
{                                                                                                                                                                                                                  
    fprintf(stderr, "%s: %s\n", f, zmq_strerror(zmq_errno()));                                                                                                                                                     
    abort();                                                                                                                                                                                                       
}

      

Doing the above using the first (manpage) form always produces:

zmq_getsockopt: Invalid argument

      

However, the second, commented form using malloc has no problem. This makes zero sense to me, since passing the address of a local variable to zmq_getsockopt is perfectly legal.

This issue only shows up in 64-bit binaries on windows; 32 bit binaries on Windows or 64 bit binaries on Linux have no problem.

This also seems to be a problem with only the ZMQ_FD socket option. ZMQ_TYPE and ZMQ_SNDHWM worked without issue.

Is there some strange behavior related to ZMQ_FD on Windows x64 that I am not aware of?

Update

So, I just noticed that my "working" code is actually wrong.

sizeof(fd)

      

takes the size of a pointer in the second form. Actually, this has nothing to do with malloc, as one day I change it to sizeof (int), as it should be EINVAL again:

/* Fail */
int *fd        = malloc(sizeof(int));                                                                                                                                                                          
size_t fd_size = sizeof(int);                                                                                                                                                                                  
rc = zmq_getsockopt(socket, ZMQ_FD, fd, &fd_size);                                                                                                                                                             
if (rc == -1) { zmq_perror("zmq_getsockopt"); }

      

Turns out I apparently need to use 64 bit integer type with ZMQ_FD on windows x64

/* Success! */
uint64_t fd;                                                                                                                                                                                                   
size_t fd_size = sizeof(uint64_t);                                                                                                                                                                             
rc = zmq_getsockopt(socket, ZMQ_FD, &fd, &fd_size);                                                                                                                                                            
if (rc == -1) { zmq_perror("zmq_getsockopt"); }

      

This is very confusing since the api for zmq_getsockopt int . This is mistake? Extracentric windows? Am I tight?

Corresponding addition:

zmq version: 3.2.3

: compiled using mingw-w64, rubenvb-4.8.0 for 64bit and 32bit binaries

os: windows 7

+1


source to share


1 answer


The zmq_getsockopt man page says:



The type of the parameter value is int on POSIX systems, SOCKET on Windows

0


source







All Articles