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.