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.