Skip to content
Advertisement

select() fails when adding m32 flag to Makefile

i have the following code, which simply creates udp socket to listen to a multicast group.

I’m compiling it using gcc, with -c -g flags, on x64 machine. When adding -m32 flag to linking & compiling phases in Makefile, select() call is failing with Invalid Argument.

After debugging a little bit with and without the flag, i found out that using the flag i get all the same values for all variables, except:

readfds: 0x80.. (repeats 31 times) – WITH -m32 flag

readfds: 0x80.. (repeats 15 times) – without the flag

sock.sin_zero: 0x5c, 0xD5, 0xff, and some other weird values WITH -m32 flag

sock.sin_zero: 0x0,0x0,0x20,0x0,0x0 – without the flag

All variables reading is done inside the file loop, right after FD_SET

I don’t really understand why does it changes at whole (as 32 bit program suppose to run just fine on 64 bit machines) , or why does select() returns Invalid Argument in that case.

could someone please help?

#include <stdio.h>
#include <stdlib.h>
#include <linux/socket.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include "radio_listener.h"

int main_loop(int argc, char *argv[])
{
    int sock_no = 0;
    struct sockaddr_in sock;
    socklen_t sock_size;
    fd_set readfds;

    struct ip_mreq mreq_ip;
    uint16_t mreq_port = 0;

    char buffer[BUFF_SIZE];
    struct timeval timeout_value;

    if(VALID_ARGC != argc)
    {
        fprintf(stderr, "usage: %s <mc_address> <udp_port>n", argv[0]);
        exit(EXIT_FAILURE);
    }

    mreq_port = atoi(argv[2]);

    /* Initialize a socket */
    sock_no = socket(AF_INET, SOCK_DGRAM, 0);
    if(sock_no < 0)
    {
        perror("socket() failed!");
        exit(1);
    }
    sock.sin_family = AF_INET;
    sock.sin_addr.s_addr = htonl(INADDR_ANY);
    sock.sin_port = htons(mreq_port);
    sock_size = sizeof(sock);

    bind(sock_no, (struct sockaddr *)&sock, sizeof(sock));

    /* Initialize the Multicast request */
    mreq_ip.imr_multiaddr.s_addr = inet_addr(argv[1]);
    mreq_ip.imr_interface.s_addr = htonl(INADDR_ANY);    

    setsockopt(sock_no, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq_ip, sizeof(mreq_ip));

    while (1)
    {
        timeout_value.tv_sec = TIMEOUT_VAL;
        FD_ZERO(&readfds);
        FD_SET(sock_no, &readfds);
        int retval = select(sock_no+1, &readfds, NULL, NULL, &timeout_value);

        if(-1 == retval)
        {
            perror("select() failed!");
            close(sock);
            exit(1);
        }
        if(0 == retval)
        {
            printf("Timeout - Closing socket and exitingn");
            break;
        }

        if(recvfrom(sock_no, buffer, BUFF_SIZE, 0, (struct sockaddr *)&sock, &sock_size) < 0)
        {
            perror("recvfrom() failed!");
            close(sock);
            exit(1);
        }

        printf("%s", buffer);
    }

    close(sock);
    return EXIT_SUCCESS;
}

int main(int argc, char *argv[])
{
    int rc = 0;
    rc = main_loop(argc, argv);

    return rc;
}

Advertisement

Answer

You’re not setting the tv_usec field of the timeout argument, so it will contain some garbage (whatever happened to be on the stack where timeout_value was allocated). If that random garbage happens to be a negative number, you’ll get the EINVAL invalid argument error. If it happens to be ok, you won’t. Minor changes to things (like using -m32 or not) will tend to change this.

User contributions licensed under: CC BY-SA
9 People found this is helpful
Advertisement