Showing posts with label glib. Show all posts
Showing posts with label glib. Show all posts

Wednesday, April 25, 2012

glib/GIO Sockets and Binding on IPv4 and IPv6

Today I learned that it isn't possible to bind to the same port on both IPv4 and IPv6 in GIO:

#include <glib.h> #include <gio/gio.h> #include <stdlib.h> #include <stdio.h> int main(int argc, const char ** argv) { char * valid; unsigned long int port; GError * err = NULL; GSocketFamily gfamily = G_SOCKET_FAMILY_IPV4; GSocket * sockets[2]; GInetAddress * giaddress; GSocketAddress * gsaddress; int i; g_type_init(); if(argc == 1) { fprintf(stderr, "Usage: %s port\n", argv[0]); return 1; } port = strtoul(argv[1], &valid, 10); if(port == 0 || port > 0xFFFF || *valid != 0) { fprintf(stderr, "Invalid port: %s\n", argv[1]); return 1; } while(gfamily != G_SOCKET_FAMILY_INVALID) { i = (gfamily == G_SOCKET_FAMILY_IPV4) ? 0 : 1; printf("Family: %d, port: %lu\n", gfamily, port); sockets[i] = g_socket_new(gfamily, G_SOCKET_TYPE_STREAM, G_SOCKET_PROTOCOL_TCP, &err); if(sockets[i] == NULL || err != NULL) { fprintf(stderr, "Failed to create server socket: %s\n", err->message); g_error_free(err); if(sockets[i] != NULL) g_object_unref(sockets[i]); return 2; } giaddress = g_inet_address_new_any(gfamily); gsaddress = g_inet_socket_address_new(giaddress, port); if(!g_socket_bind(sockets[i], gsaddress, TRUE, &err) || err != NULL) { fprintf(stderr, "Failed to bind to port: %s\n", err->message); g_error_free(err); if(sockets[i] != NULL) g_object_unref(sockets[i]); if(gsaddress != NULL) g_object_unref(gsaddress); return 2; } if(!g_socket_listen(sockets[i], &err) || err != NULL) { fprintf(stderr, "Failed to listen on socket: %s\n", err->message); g_error_free(err); if(sockets[i] != NULL) g_object_unref(sockets[i]); if(gsaddress != NULL) g_object_unref(gsaddress); return 2; } gfamily = (gfamily == G_SOCKET_FAMILY_IPV4) ? G_SOCKET_FAMILY_IPV6 : G_SOCKET_FAMILY_INVALID; } for(i = 0; i < 2; i++) g_object_unref(sockets[i]); return 0; }

Typical output:

% ./gfail 3000 Family: 2, port: 3000 Family: 10, port: 3000 Failed to bind to port: Error binding to address: Address already in use

Weird.

Thursday, March 8, 2012

g_strdup and g_free Corruption

I just looked further into it, and realized my actual mistake below. Whoops!

I found an interesting little nit when messing around while researching glib's behavior:

#include <glib.h> #include <string.h> int main(int argc, char ** argv) { gchar * foo; foo = g_strdup("100"); g_free(foo); g_printf("FOO: %p\n", foo); gchar * bar = g_strdup(foo); g_printf("BAR: %p = '%s'\n", bar, bar); g_free(bar); if(foo == bar) g_printf("FOO == BAR\n"); g_free(foo); return 0; }% ./gnfree2 FOO: 0x16ad010 BAR: 0x16ad010 = '' FOO == BAR *** glibc detected *** ./gnfree2: double free or corruption (fasttop): 0x00000000016ad010 *** ======= Backtrace: ========= /lib/libc.so.6(+0x78e66)[0x7fa8a16f9e66] ./gnfree2[0x40073e] /lib/libc.so.6(__libc_start_main+0xed)[0x7fa8a16a238d] ./gnfree2[0x4005e9] ======= Memory map: ======== 00400000-00401000 r-xp 00000000 08:04 418428329 /home/nehodges/Programs/gnfree2 00600000-00601000 rw-p 00000000 08:04 418428329 /home/nehodges/Programs/gnfree2 016ad000-016ce000 rw-p 00000000 00:00 0 [heap] 7fa8a0ded000-7fa8a0e02000 r-xp 00000000 08:03 131410 /usr/lib/libgcc_s.so.1 7fa8a0e02000-7fa8a1002000 ---p 00015000 08:03 131410 /usr/lib/libgcc_s.so.1 7fa8a1002000-7fa8a1003000 rw-p 00015000 08:03 131410 /usr/lib/libgcc_s.so.1 7fa8a1003000-7fa8a101a000 r-xp 00000000 08:03 2359314 /lib/libpthread-2.15.so 7fa8a101a000-7fa8a1219000 ---p 00017000 08:03 2359314 /lib/libpthread-2.15.so 7fa8a1219000-7fa8a121a000 r--p 00016000 08:03 2359314 /lib/libpthread-2.15.so 7fa8a121a000-7fa8a121b000 rw-p 00017000 08:03 2359314 /lib/libpthread-2.15.so 7fa8a121b000-7fa8a121f000 rw-p 00000000 00:00 0 7fa8a121f000-7fa8a1226000 r-xp 00000000 08:03 2359337 /lib/librt-2.15.so 7fa8a1226000-7fa8a1425000 ---p 00007000 08:03 2359337 /lib/librt-2.15.so 7fa8a1425000-7fa8a1426000 r--p 00006000 08:03 2359337 /lib/librt-2.15.so 7fa8a1426000-7fa8a1427000 rw-p 00007000 08:03 2359337 /lib/librt-2.15.so 7fa8a1427000-7fa8a1480000 r-xp 00000000 08:03 135459 /usr/lib/libpcre.so.1.0.0 7fa8a1480000-7fa8a167f000 ---p 00059000 08:03 135459 /usr/lib/libpcre.so.1.0.0 7fa8a167f000-7fa8a1680000 r--p 00058000 08:03 135459 /usr/lib/libpcre.so.1.0.0 7fa8a1680000-7fa8a1681000 rw-p 00059000 08:03 135459 /usr/lib/libpcre.so.1.0.0 7fa8a1681000-7fa8a1818000 r-xp 00000000 08:03 2359610 /lib/libc-2.15.so 7fa8a1818000-7fa8a1a18000 ---p 00197000 08:03 2359610 /lib/libc-2.15.so 7fa8a1a18000-7fa8a1a1c000 r--p 00197000 08:03 2359610 /lib/libc-2.15.so 7fa8a1a1c000-7fa8a1a1e000 rw-p 0019b000 08:03 2359610 /lib/libc-2.15.so 7fa8a1a1e000-7fa8a1a22000 rw-p 00000000 00:00 0 7fa8a1a22000-7fa8a1b15000 r-xp 00000000 08:03 135544 /usr/lib/libglib-2.0.so.0.3000.2 7fa8a1b15000-7fa8a1d14000 ---p 000f3000 08:03 135544 /usr/lib/libglib-2.0.so.0.3000.2 7fa8a1d14000-7fa8a1d15000 r--p 000f2000 08:03 135544 /usr/lib/libglib-2.0.so.0.3000.2 7fa8a1d15000-7fa8a1d16000 rw-p 000f3000 08:03 135544 /usr/lib/libglib-2.0.so.0.3000.2 7fa8a1d16000-7fa8a1d17000 rw-p 00000000 00:00 0 7fa8a1d17000-7fa8a1d38000 r-xp 00000000 08:03 2360114 /lib/ld-2.15.so 7fa8a1f02000-7fa8a1f06000 rw-p 00000000 00:00 0 7fa8a1f34000-7fa8a1f37000 rw-p 00000000 00:00 0 7fa8a1f37000-7fa8a1f38000 r--p 00020000 08:03 2360114 /lib/ld-2.15.so 7fa8a1f38000-7fa8a1f39000 rw-p 00021000 08:03 2360114 /lib/ld-2.15.so 7fa8a1f39000-7fa8a1f3a000 rw-p 00000000 00:00 0 7fff47234000-7fff47255000 rw-p 00000000 00:00 0 [stack] 7fff4738e000-7fff4738f000 r-xp 00000000 00:00 0 [vdso] ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall] zsh: abort ./gnfree2

Granted, one shouldn't be writing code that runs into this case, but it's kind of funny.