# Crash on gc\_mark()

**URL:** <https://www.ruby-forum.com/t/crash-on-gc-mark/67221>\
**Category:** Development\
**Created:** [September 1, 2006, 12:43pm UTC](https://www.ruby-forum.com/t/crash-on-gc-mark/67221 "2006-09-01T12:43:58Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![Abhisek\_Datta](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/f17d59/32.png) [@Abhisek\_Datta](https://www.ruby-forum.com/u/Abhisek_Datta)\
**Post date:** [September 1, 2006, 12:43pm UTC](https://www.ruby-forum.com/t/crash-on-gc-mark/67221/1 "2006-09-01T12:43:58Z")

</div>

Hi,

I am doing a Ruby binding for libnids library  
([http://libnids.sourceforge.net](http://libnids.sourceforge.net))

Libnids uses callback functions which are triggered on packet capture.  
Now apparently my binding is working fine, but it is crashing after  
capturing for around 5-10 minutes.

Crash looks like this:

[DATA] 192.168.0.49:52071 → 63.245.209.21:80 [SEND: 474] [RECV: 0]  
[NEW CONNECTION] 192.168.0.49:55510 → 213.150.45.196:80  
examples/tcp.rb:12: [BUG] Segmentation fault  
ruby 1.8.4 (2005-12-24) [i686-linux]

A gdb backtrace looks like this:

#0 0xb7d20941 in kill () from /lib/libc.so.6  
#1 0xb7d206e5 in raise () from /lib/libc.so.6  
#2 0xb7d21a66 in abort () from /lib/libc.so.6  
#3 0xb7e9a5dc in rb\_bug () from /usr/lib/libruby18.so.1.8  
#4 0xb7ebac79 in rb\_gc\_mark () from /usr/lib/libruby18.so.1.8  
#5 0xb7eba862 in rb\_mark\_tbl () from /usr/lib/libruby18.so.1.8  
#6 0xb7f00b6f in st\_foreach () from /usr/lib/libruby18.so.1.8  
#7 0xb7eba89f in rb\_mark\_tbl () from /usr/lib/libruby18.so.1.8  
#8 0xb7ebab8b in rb\_gc\_mark () from /usr/lib/libruby18.so.1.8  
#9 0xb7eba7a9 in rb\_source\_filename () from /usr/lib/libruby18.so.1.8  
#10 0xb7ebb844 in rb\_gc\_mark\_frame () from /usr/lib/libruby18.so.1.8  
#11 0xb7eba3c3 in rb\_newobj () from /usr/lib/libruby18.so.1.8  
#12 0xb7f00c69 in st\_foreach () from /usr/lib/libruby18.so.1.8  
#13 0xb7f00cdf in st\_foreach () from /usr/lib/libruby18.so.1.8  
#14 0xb7f00d71 in rb\_str\_new () from /usr/lib/libruby18.so.1.8  
#15 0xb7f00db3 in rb\_str\_new2 () from /usr/lib/libruby18.so.1.8  
#16 0xb7ecf750 in rb\_fix2str () from /usr/lib/libruby18.so.1.8  
#17 0xb7ecf7ef in rb\_fix2str () from /usr/lib/libruby18.so.1.8  
#18 0xb7eb46f3 in rb\_throw () from /usr/lib/libruby18.so.1.8  
#19 0xb7ea7918 in rb\_with\_disable\_interrupt () from  
/usr/lib/libruby18.so.1.8  
#20 0xb7ea8214 in rb\_with\_disable\_interrupt () from  
/usr/lib/libruby18.so.1.8  
#21 0xb7ea854a in rb\_apply () from /usr/lib/libruby18.so.1.8  
#22 0x000000a1 in ?? ()  
#23 0x00000c51 in ?? ()  
#24 0x00000000 in ?? ()

Crash occurs on the following extension code:

static void libnids\_internal\_register\_tcp(struct tcp\_stream \*ts, void  
\*\*param)  
{  
VALUE client\_data;  
VALUE client\_data\_offset;  
VALUE client\_data\_len;  
VALUE client\_data\_new\_len;  
VALUE client\_state;  
VALUE server\_data;  
VALUE server\_data\_offset;  
VALUE server\_data\_len;  
VALUE server\_data\_new\_len;  
VALUE server\_state;  
VALUE nids\_state;  
VALUE src\_addr;  
VALUE dst\_addr;  
VALUE src\_port;  
VALUE dst\_port;  
VALUE hash;

DEBUG\_PRINT(“TCP callback triggered”);

if(rb\_object\_tcp\_cb == (VALUE) NULL) {  
DEBUG\_PRINT(“TCP callback method not set”);  
return;  
}

src\_addr = rb\_str\_new2((char\*)inet\_ntoa(_((struct  
in\_addr_)&(ts-\>addr.saddr))));  
dst\_addr = rb\_str\_new2((char\*)inet\_ntoa(_((struct  
in\_addr_)&(ts-\>addr.daddr))));  
src\_port = INT2FIX(ts-\>addr.source);  
dst\_port = INT2FIX(ts-\>addr.dest);

client\_data = rb\_str\_new2(“”);  
server\_data = rb\_str\_new2(“”);  
client\_data\_offset = INT2FIX(0);  
client\_data\_len = INT2FIX(0);  
client\_data\_new\_len = INT2FIX(0);  
server\_data\_offset = INT2FIX(0);  
server\_data\_len = INT2FIX(0);  
server\_data\_new\_len = INT2FIX(0);

nids\_state = INT2FIX(ts-\>nids\_state);

switch(ts-\>nids\_state) {  
case NIDS\_JUST\_EST:  
ts-\>client.collect++;  
ts-\>server.collect++;  
break;

```
  case NIDS_DATA:
     client_data = rb_str_cat(client_data, ts->client.data,

```

ts-\>client.count);  
client\_data\_offset = INT2FIX(ts-\>client.offset);  
client\_data\_len = INT2FIX(ts-\>client.count);  
client\_data\_new\_len = INT2FIX(ts-\>client.count\_new);

```
     server_data = rb_str_cat(server_data, ts->server.data,

```

ts-\>server.count);  
server\_data\_offset = INT2FIX(ts-\>server.offset);  
server\_data\_len = INT2FIX(ts-\>server.count);  
server\_data\_new\_len = INT2FIX(ts-\>server.count\_new);

```
     break;

  default:
     DEBUG_PRINT("Unknown nids state from TCP callback");
     return;

```

}

hash = rb\_hash\_new();

rb\_hash\_aset(hash, rb\_str\_new2(“saddress”), src\_addr);  
rb\_hash\_aset(hash, rb\_str\_new2(“daddress”), dst\_addr);  
rb\_hash\_aset(hash, rb\_str\_new2(“sport”), src\_port);  
rb\_hash\_aset(hash, rb\_str\_new2(“dport”), dst\_port);  
rb\_hash\_aset(hash, rb\_str\_new2(“nids\_state”), nids\_state);  
rb\_hash\_aset(hash, rb\_str\_new2(“client\_state”), client\_state);  
rb\_hash\_aset(hash, rb\_str\_new2(“client\_data”), client\_data);  
rb\_hash\_aset(hash, rb\_str\_new2(“client\_data\_offset”),  
client\_data\_offset);  
rb\_hash\_aset(hash, rb\_str\_new2(“client\_data\_len”), client\_data\_len);  
rb\_hash\_aset(hash, rb\_str\_new2(“client\_data\_new\_len”),  
client\_data\_new\_len);  
rb\_hash\_aset(hash, rb\_str\_new2(“server\_state”), server\_state);  
rb\_hash\_aset(hash, rb\_str\_new2(“server\_data”), server\_data);  
rb\_hash\_aset(hash, rb\_str\_new2(“server\_data\_offset”),  
server\_data\_offset);  
rb\_hash\_aset(hash, rb\_str\_new2(“server\_data\_len”), server\_data\_len);  
rb\_hash\_aset(hash, rb\_str\_new2(“server\_data\_new\_len”),  
server\_data\_new\_len);

rb\_funcall(rb\_cObject, rb\_intern(“send”),  
2,  
rb\_object\_tcp\_cb,  
hash);

//DEBUG\_PRINT(“Invoking garbage collector”);  
//rb\_funcall(rb\_mGC, rb\_intern(“start”), 0);

return;  
}

Amazingly if I uncomment the last two lines in the above function and  
let the garbage collector to run then ruby is aborted immediately with  
the following result:

compaq ruby-libnids # ruby examples/tcp.rb  
[NEW CONNECTION] 192.168.0.49:54346 → 216.239.63.19:443  
[DATA] 192.168.0.49:54346 → 216.239.63.19:443 [SEND: 120] [RECV: 0]  
examples/tcp.rb:22: [BUG] rb\_gc\_mark(): unknown data type  
0x2f(0x8078b28) non object  
ruby 1.8.4 (2005-12-24) [i686-linux]

Aborted

I am quite new to ruby extension development, so I think I might be  
doing something wrong.  
Some pointers will be useful.

Thanks,

abhisek

---

<div class="post-metadata">

**Author:** ![Abhisek\_Datta](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/f17d59/32.png) [@Abhisek\_Datta](https://www.ruby-forum.com/u/Abhisek_Datta)\
**Post date:** [September 4, 2006, 2:46pm UTC](https://www.ruby-forum.com/t/crash-on-gc-mark/67221/2 "2006-09-04T14:46:39Z")

</div>

Hi,

In message “Re: [ruby-dev:29372] Crash on gc\_mark()”  
on Fri, 1 Sep 2006 16:16:50 +0900, “Abhisek Datta”  
[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) writes:

|Libnids uses callback functions which are triggered on packet capture.  
|Now apparently my binding is working fine, but it is crashing after  
|capturing for around 5-10 minutes.  
|  
|Crash looks like this:

You haven’t initialized local variables client\_state and server\_state,  
so that hash refers uninitialized non-object garbage. That’s the  
reason why GC crashed.

```
						matz.

```
