Older blog entries for ged (starting at number 4)

MUES Progress

I synch'ed CVS with the latest version of the code last night. There's still a few bugfixes that I've since written, but not yet committed, but they too will be in CVS a little later tonight. Changelogs are here.

Through judicious use of the Observer pattern, I replaced the polling loop in the IOEventStream class with a loop that locks a ConditionVariable. The condition variable is signalled whenever one of the Subject objects calls update(), so now IO is only done when there are actual pending events. It had the side-effect of cleaning up the code, too, which is always a good sign. Load average in the IOEventStream test harness with no keyboard activity: 0.02.

I'm now working through some issues with the way login events are handled, and I realized that the reconnect() method is too tightly coupled to the SocketOutputFilter, so I'll see if I can come up with a more elegant implementation tonight.

14 May 2001 (updated 14 May 2001 at 08:07 UTC) »

Icebox Hacking

I converted all of the mod_perl handlers in the Icebox project to method handlers yesterday, and derived them all from a base ApacheHandler.pm class that I wrote for a client. It's nice to see the code shrink so much, and to be able to refactor lots of the common tasks out of the individual classes into a common base class.

The stream daemon is nearly done, so I should be releasing a 1.0 version of Icebox soonish.

9 May 2001 (updated 9 May 2001 at 06:55 UTC) »

MUES Progress

I've decoupled the IO stream away from the server to the point now that I only have to supply some vague simulcrum of the Engine's interface and the event subsystem to be able to test all the IO subsystems in standalone test harnesses.

I am removing all the player/stream login code from the LoginSession class and the Engine's LoginSessionAuthEvent handler and moving it to the Engine's PlayerLoginEvent handler for consolidation. This means that the IOEventStream will have to be frozen for a second when it's handed via the PlayerLoginEvent back to the Engine to prevent IOEvents from being lost in a race to re-assign the socket from the stream in the event of a reconnect. I added pause() and unpause() to the stream class to facilitate this.

The IOEventStream is still a CPU hog. It's a hog because it has no way of knowing if its filters have pending events, and so must poll them in a timely manner. If the interval is adjusted too high, response to the shell becomes sluggish. This can be fixed by arranging for some kind of signalling mechanism for filters so that they can wake the stream when they have events pending, and the stream can run the events through the loop and then sleep until there's more to be done. Perhaps mutexen or condition variables or a semaphore could be used to do this. More experiments are needed.

13 Apr 2001 (updated 13 Apr 2001 at 10:16 UTC) »
TableAdapter ObjectStore is segfaulting

galendril pts/2 [~/source/ruby/MUES/Ruby-MUES]
174/674 {0}$ gdb ruby
GNU gdb 5.0
Copyright 2000 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public
License, and you are
welcome to change it and/or distribute copies of it under
certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show
warranty" for details.
This GDB was configured as "i686-pc-linux-gnu"...
(gdb) run experiments/playerFetcher.rb
Starting program: /usr/bin/ruby experiments/playerFetcher.rb
Connecting to mues@localhost as '' identified by 'lamePass'
for db 'localhost:mues:'

Program received signal SIGSEGV, Segmentation fault. __strtol_internal (nptr=0x1 <Address 0x1 out of bounds>, endptr=0x9c, base=65536, group=589831) at eval.c:36 36 { (gdb) bt #0 __strtol_internal (nptr=0x1 <Address 0x1 out of bounds>, endptr=0x9c, base=65536, group=589831) at eval.c:36 #1 0x40469655 in __db_calloc (num=1, size=156) at os/os_alloc.c:69 #2 0x404629fe in __nss_db_open (fname=0x4044e6f5 "/var/db/services.db", type=DB_BTREE, flags=65536, mode=0, dbenv=0x0, dbinfo=0x0, dbpp=0x4044f9b0) at db/db.c:159 #3 0x4044bd4d in internal_setent (stayopen=0) at nss_files/../nss_db/db-XXX.c:67 #4 0x4044bf5e in lookup (key=0xbfff660c, result=0x40236b3c, buffer=0x80ab068, buflen=1024, errnop=0x40234800) at nss_files/../nss_db/db-XXX.c:173 #5 0x4044c1e4 in _nss_db_getservbyname_r (name=0x402c4f4b "mysql", proto=0x402c4f47 "tcp", result=0x40236b3c, buffer=0x80ab068 "8 #@8 #@", buflen=1024, errnop=0x40234800) at nss_files/files-service.c:44 #6 0x40202fb4 in __getservbyname_r (name=0x402c4f4b "mysql", proto=0x402c4f47 "tcp", resbuf=0x40236b3c, buffer=0x80ab068 "8 #@8 #@", buflen=1024, result=0xbfff66d0) at ../nss/getXXbyYY_r.c:200 #7 0x40202e55 in getservbyname (name=0x402c4f4b "mysql", proto=0x402c4f47 "tcp") at ../nss/getXXbyYY.c:145 #8 0x402b5adc in mysql_once_init () from /usr/local/mysql/lib/mysql/libmysqlclient.so.10 #9 0x402b7cdb in mysql_init () from /usr/local/mysql/lib/mysql/libmysqlclient.so.10 #10 0x40027197 in real_connect () at eval.c:88 #11 0x4005037c in call_cfunc (func=0x40026fe0 <real_connect>, recv=1076124376, len=-1, argc=4, argv=0xbfff6b7c) at eval.c:4168 #12 0x40050988 in rb_call0 (klass=1076124356, recv=1076124376, id=10649, argc=4, argv=0xbfff6b7c, body=0x402459d4, nosuper=1) at eval.c:4307 #13 0x4005111c in rb_call (klass=1076124356, recv=1076124376, mid=10649, argc=4, argv=0xbfff6b7c, scope=0) at eval.c:4507 #14 0x4004ba61 in rb_eval (self=1076913620, n=0x4025b464) at eval.c:2511 #15 0x4004b5e0 in rb_eval (self=1076913620, n=0x4025b43c) at eval.c:2488 #16 0x40049fa3 in rb_eval (self=1076913620, n=0x4025b798) at eval.c:1995 #17 0x40050d42 in rb_call0 (klass=1076987900, recv=1076913620, id=14009, argc=0, argv=0x0, body=0x4025b798, nosuper=0) at eval.c:4419 #18 0x4005111c in rb_call (klass=1076987900, recv=1076913620, mid=14009, argc=0, argv=0x0, scope=0) at eval.c:4507 #19 0x4004ba61 in rb_eval (self=1076913320, n=0x40318edc) at eval.c:2511 #20 0x4004c487 in rb_eval (self=1076913320, n=0x40318ec8) at eval.c:2660 #21 0x40049fa3 in rb_eval (self=1076913320, n=0x40318e28) at eval.c:1995 #22 0x4004eb33 in rb_yield_0 (val=4, self=1076913320, klass=0, acheck=0) at eval.c:3563 #23 0x4004ae0d in rb_eval (self=1076913260, n=0x4028ceb4) at eval.c:2325 #24 0x4004b107 in rb_eval (self=1076913260, n=0x4028ce14) at eval.c:2375 #25 0x40050d42 in rb_call0 (klass=1076400140, recv=1076913260, id=11801, argc=0, argv=0x0, body=0x4028ce14, nosuper=0) at eval.c:4419 #26 0x4005111c in rb_call (klass=1076400140, recv=1076913260, mid=11801, argc=0, argv=0x0, scope=0) at eval.c:4507 #27 0x4004ba61 in rb_eval (self=1076913320, n=0x40318f54) at eval.c:2511 #28 0x4004aa1d in rb_eval (self=1076913320, n=0x40318cc0) at eval.c:2246 #29 0x40050d42 in rb_call0 (klass=1076988440, recv=1076913320, id=15161, argc=0, argv=0x0, body=0x40318cc0, nosuper=0) at eval.c:4419 #30 0x4005111c in rb_call (klass=1076988440, recv=1076913320, mid=15161, argc=0, argv=0x0, scope=1) at eval.c:4507 #31 0x4004ba61 in rb_eval (self=1076913320, n=0x4031a8e0) at eval.c:2511 #32 0x40049fa3 in rb_eval (self=1076913320, n=0x4031a778) at eval.c:1995 #33 0x40050d42 in rb_call0 (klass=1076988440, recv=1076913320, id=6033, argc=0, argv=0xbfffaf80, body=0x4031a778, nosuper=0) at eval.c:4419 #34 0x4005111c in rb_call (klass=1076988440, recv=1076913320, mid=6033, argc=1, argv=0xbfffaf7c, scope=0) at eval.c:4507 #35 0x4004ba61 in rb_eval (self=1076913320, n=0x40319968) at eval.c:2511 #36 0x4004eb33 in rb_yield_0 (val=1, self=1076913320, klass=0, acheck=0) at eval.c:3563 #37 0x4004edb9 in rb_yield (val=1) at eval.c:3647 #38 0x40044061 in collect_i (i=1, tmp=1076913160) at enum.c:145 #39 0x4004eb18 in rb_yield_0 (val=1, self=1076268176, klass=0, acheck=0) at eval.c:3560 ---Type <return> to continue, or q <return> to quit--- #40 0x4004edb9 in rb_yield (val=1) at eval.c:3647 #41 0x4008cb42 in range_each (range=1076913220) at range.c:153 #42 0x4005038a in call_cfunc (func=0x4008caac <range_each>, recv=1076913220, len=0, argc=0, argv=0x0) at eval.c:4171 #43 0x40050988 in rb_call0 (klass=1076236136, recv=1076913220, id=3561, argc=0, argv=0x0, body=0x40260eb4, nosuper=1) at eval.c:4307 #44 0x4005111c in rb_call (klass=1076236136, recv=1076913220, mid=3561, argc=0, argv=0x0, scope=1) at eval.c:4507 #45 0x4005139c in rb_funcall (recv=1076913220, mid=3561, n=0) at eval.c:4581 #46 0x40043cea in rb_each (obj=1076913220) at enum.c:23 #47 0x4004f54e in rb_iterate (it_proc=0x40043cc4 <rb_each>, data1=1076913220, bl_proc=0x4004403c <collect_i>, data2=1076913160) at eval.c:3816 #48 0x40044135 in enum_collect (obj=1076913220) at enum.c:176 #49 0x4005038a in call_cfunc (func=0x400440f4 <enum_collect>, recv=1076913220, len=0, argc=0, argv=0x0) at eval.c:4171 #50 0x40050988 in rb_call0 (klass=1076236096, recv=1076913220, id=3505, argc=0, argv=0x0, body=0x402687b8, nosuper=1) at eval.c:4307 #51 0x4005111c in rb_call (klass=1076236096, recv=1076913220, mid=3505, argc=0, argv=0x0, scope=0) at eval.c:4507 #52 0x4004ba61 in rb_eval (self=1076913320, n=0x40319a08) at eval.c:2511 #53 0x4004aa1d in rb_eval (self=1076913320, n=0x4031992c) at eval.c:2246 #54 0x40050d42 in rb_call0 (klass=1076988440, recv=1076913320, id=335, argc=0, argv=0xbfffc968, body=0x4031992c, nosuper=0) at eval.c:4419 #55 0x4005111c in rb_call (klass=1076988440, recv=1076913320, mid=335, argc=1, argv=0xbfffc964, scope=0) at eval.c:4507 #56 0x4004ba61 in rb_eval (self=1076913720, n=0x40271e84) at eval.c:2511 #57 0x40050d42 in rb_call0 (klass=1076985520, recv=1076913720, id=9321, argc=0, argv=0xbfffd038, body=0x40271e84, nosuper=0) at eval.c:4419 #58 0x4005111c in rb_call (klass=1076985520, recv=1076913720, mid=9321, argc=1, argv=0xbfffd034, scope=0) at eval.c:4507 #59 0x4004ba61 in rb_eval (self=1076369540, n=0x40257ef4) at eval.c:2511 #60 0x4004c433 in rb_eval (self=1076369540, n=0x40257ee0) at eval.c:2650 #61 0x40049fa3 in rb_eval (self=1076369540, n=0x40257ecc) at eval.c:1995 #62 0x40050d42 in rb_call0 (klass=1076370180, recv=1076369540, id=8993, argc=0, argv=0xbfffe108, body=0x40257ecc, nosuper=0) at eval.c:4419 #63 0x4005111c in rb_call (klass=1076370180, recv=1076369540, mid=8993, argc=1, argv=0xbfffe104, scope=0) at eval.c:4507 #64 0x4004ba61 in rb_eval (self=1076268176, n=0x4025b98c) at eval.c:2511 #65 0x4004c433 in rb_eval (self=1076268176, n=0x4025b978) at eval.c:2650 #66 0x40049fa3 in rb_eval (self=1076268176, n=0x4025ba2c) at eval.c:1995 #67 0x40047adb in eval_node (self=1076268176, node=0x4025ba2c) at eval.c:1076 #68 0x40047f69 in ruby_run () at eval.c:1206 #69 0x80486a6 in main (argc=2, argv=0xbffff1bc, envp=0xbffff1c8) at main.c:50 #70 0x40140e6a in __libc_start_main (main=0x8048678 <main>, argc=2, ubp_av=0xbffff1bc, init=0x80484ec <_init>, fini=0x80486f4 <_fini>, rtld_fini=0x4000daa4 <_dl_fini>, stack_end=0xbffff1ac) at ../sysdeps/generic/libc-start.c:129

I suspect the fact that I tried to store per-class metadata in class attributes is at least partially responsible for the segfaults. I didn't realize they were inherited by child classes.

But how to store the per-class metadata, since class attributes are inherited, and setting them in child classes changes the value of the parent's attributes instead of overriding them?

Maybe with a binding? But where to store the binding?

Maybe there should be a class attribute for TableAdapter that holds Hashes for all of its children's metadata? Some mechanism for avoiding class name collision and allowing storage for anonymous subclasses?

13 Apr 2001 (updated 13 Apr 2001 at 09:32 UTC) »

Hmmm... I guess I shouldn't let iThought do HTML conversion...

New Advogato Features

New HTML Parser: The long-awaited libxml2 based HTML parser code is live. It needs further work but already handles most markup better than the original parser.

Keep up with the latest Advogato features by reading the Advogato status blog.

If you're a C programmer with some spare time, take a look at the mod_virgule project page and help us with one of the tasks on the ToDo list!