Six Years of Space Nerds In Space

•November 3, 2018 • Leave a Comment

November 3rd, 2018 — Six years ago I began working on Space Nerds in Space as a hobby project, little knowing what it would become.

Sunday Morning Debugging

•September 16, 2018 • Leave a Comment

Sunday, September 16, 2018 — This morning I experienced an unexpected crash of snis_client shortly after making a warp gate jump from one solarsystem to another. While a crash is not an earth shaking surprise, they generally happen while I’m in the midst of working on something, and generally have some relation to what I’m working on. In this case, I couldn’t think of anything I had done recently that should be causing snis_client to crash.

Luckily, I had just compiled without optimization, but unluckily, I had forgotten to type “ulimit -c unlimited”, so I didn’t get a core file. Rats. Well, better luck next time. I tried for about 15 minutes to get the crash to happen again, but without any clear idea of what the cause might have been, I didn’t have any luck.

Then I remembered to look in /var/log/syslog:

wombat space-nerds-in-space # grep snis /var/log/syslog
Sep 16 09:49:48 wombat kernel: [ 6809.248896] snis_client[14897]: segfault at ab000925ddc ip 0000000000488f71 sp 00007ffe800e19d0 error 4 in snis_client[400000+108000]

So that number after “ip” is the address of the instruction pointer at the time of the crash. So let’s fire up gdb…

wombat space-nerds-in-space $ gdb ./snis_client
[...]
(gdb) info symbol 0x0000000000488f71
show_death_screen + 800 in section .text

Apparently the crash happened 800 bytes into the function show_death_screen().

show_death_screen()? That’s interesting. Apparently my crew had somehow died one way or another whilst in the midst of warping from one solarsystem to another!

Disassembling the region around the crash:

(gdb) dissassemble show_death_screen
[... many lines omitted ...]
   0x0000000000488f5c <779>:	mov    0x284516(%rip),%eax        # 0x70d478 <my_ship_oid>
   0x0000000000488f62 <785>:	mov    %eax,%eax
   0x0000000000488f64 <787>:	imul   $0xab0,%rax,%rax
   0x0000000000488f6b <794>:	add    $0x92688c,%rax
   0x0000000000488f71 <800>:	mov    (%rax),%edx
   0x0000000000488f73 <802>:	lea    -0x70(%rbp),%rax
   0x0000000000488f77 <806>:	mov    $0x4ee175,%esi
   0x0000000000488f7c <811>:	mov    %rax,%rdi
   0x0000000000488f7f <814>:	mov    $0x0,%eax
   0x0000000000488f84 <819>:	callq  0x4100a0 <sprintf@plt>
[...]

It looks like it’s setting up to call sprintf, and just before that, accessing a variable my_ship_oid, which is supposed to contain an index into a global “game object” array, go[] for short. The index it is supposed to contain corresponds to the go[] array entry that contains data for the player’s ship. Here’s the corresponding C code around the crash site:

10634                   sprintf(buf, "RESPAWNING IN %d SECONDS", go[my_ship_oid].respawn_time);
10635                   sng_abs_xy_draw_string(buf, TINY_FONT, txx(20), txy(500));
10636           }

From that, I expect my_ship_oid was not a valid index into the go[] array at the time of the crash. How could that be? Well, the last thing I did was warp into a new solarsystem, which involves the snis_client process disconnecting from one snis_server process and connecting to another, different snis_server process. One of the things that happens during the handshaking process is the snis_server process sends the object ID to use for the player’s ship over to the client. On the client side, the code to accept this information looks like this:

static int process_client_id_packet(void)
{
        unsigned char buffer[100];
        uint32_t id;
        int rc;

        assert(sizeof(buffer) > sizeof(struct client_ship_id_packet) - sizeof(uint8_t));
        rc = read_and_unpack_buffer(buffer, "w", &id);
        if (rc)
                return rc;
        my_ship_id = id;
        my_ship_oid = UNKNOWN_ID;

UNKNOWN_ID has the value -1 (or 0xffffffff if interpreted as an unsigned int), which is not a valid index into the go[] array.

Necessarily, this happens before the snis_client has determined an entry in the go[] array to use for the player ship. So there is a short period of time immediately after warping into a solarsystem (connecting to a snis_server process) during which my_ship_oid does not contain a valid index into the go[] array.

So what this means is whenever I need to access go[my_ship_oid}, I need to be careful that my_ship_oid is valid. Turns out that most of these accesses are encapsulated in a single function, find_my_ship(), and most of the time, it’s already done safely, but there were a few places where it wasn’t done safely, and if your crew happened to asphyxiate just as they warped into a new solarsystem, the code tripped over one of these unsafe accesses.

I should point out there is an additional hazard to watch out for, which is multithreading. That is to say, it’s not enough to check that my_ship_oid is valid, this check, and the usage of my_ship_oid must occur with the protection of a mutex, so that it isn’t modified by another thread between the safety check and the usage. In this case, that holds true because show_death_screen is called from main_da_expose(), and that is triggered by a call to gdk_window_invalidate_rect() from within advance_game() while the universe_mutex is held.

The fix for this problem is here.

Space Monsters!

•February 26, 2018 • Leave a Comment

February 26, 2018 — I’ve been working on adding Space Monsters into Space Nerds In Space.

 

I had worked on this before, but in my previous implementation, all the work of generating the space monster’s tentacle movements was done on the server side, and a lot of per-tentacle-segment information was transmitted from the server to each client, which was not a very good design, and I had never pushed any of this code to the main repository.  This new implementation avoids that problem. The motion of the tentacles is random. On the server side, a new per-monster seed value is periodically generated and transmitted to the clients. The clients use this to seed a per-monster Mersenne Twister which is then used to generate new desired tentacle segment joint angles, and the monster’s tentacles are gradually moved to conform to these new desired angles. The result is that multiple clients will see the monsters with consistent tentacle positions which are all genereted client side, with only the seed generated on the server and transmitted over the network. It seems to work quite well.

The space monsters are made from two meshes, one for the head or torso, and one for each tentacle segment. The albedo and emittance textures are static, and are derived from Gray Scott reaction diffusion patterns. The variable lighting effect is done by passing an emittance intensity value to the shader which is used to modulate the emittance color values.

Some problems remain. The tentacles do not avoid each other, and may pass through one another. I think this is a pretty hard problem to solve without unduly restricting each tentacle’s range of motion.

I still need to work on the behavior of the space monsters. Right now, they periodically choose a new random direction and change course to begin moving in that direction, and that is the extent of it. When velocity is low, this can produce rapid and very unnatural looking rotations, as only the overall velocity is controlled, while the orientation is simply derived from the velocity by making the space monster’s mouth face in the direction of motion.

Space Nerds In Space Navigation Tutorial

•December 4, 2017 • Leave a Comment

December 4, 2017 — Here’s a tutorial about how the Navigation screen works in Space Nerds In Space.

On Creativity

•October 20, 2017 • Leave a Comment

October 19, 2017

One time, a long long time ago, more than quarter century ago actually, a friend and I were talking, and he asked me, “Do you think of yourself as a creative person?” And I said, “Sure, of course.” He said, “So, on a scale of 1 to 10, how creative?” And I said, “I guess about 8 or 9.” After that, the topic of conversation drifted to something else. But the next morning, and for many days after, I couldn’t stop thinking about this conversation, and I thought to myself, “8 or 9, huh? So you think you’re more creative than 80 or 90 percent of people? Ok, if you’re so creative, Mr. 8 or 9, then where’s all the stuff you’ve created?” And I didn’t really have a good answer. And this conversation and this question has stuck with me through all these years, “If you’re so creative, then where’s all the stuff you’ve created?” And it’s kind of served as something to drive me to complete things even when I’ve become a bit bored of them. And now, many years later, I have quite a few things that I’ve created that I can point to and am proud of, and if it weren’t for that conversation way back then, I strongly suspect this wouldn’t be nearly so true.

Adding a Real Time Strategy game into Space Nerds In Space

•October 19, 2017 • Leave a Comment

October 18, 2017 — Adding a Real Time Strategy game into Space Nerds in Space.

Leaving Google

•October 12, 2017 • 1 Comment

October 12, 2017 — So I’ve left Google. Last Friday, Oct 6, 2017 was my last day working there. It was a very interesting and overall a super positive experience working at Google for the last few years, but still, I’ve left. Why? A few reasons:

  • I’ve managed to save up enough money that I don’t actually need a job at all anymore, with reasonable but not lavish expenses. I will need to leave the Bay Area pretty soon of course, since rent is pretty lavish around these parts. I’ll miss the weather, and the close access to the gorgeousness of California for sure.
  • While the first 1.5 years or so at Google were super interesting, mainly learning how all the Google stuff works, after awhile once the novelty wore off it became less interesting — not easy by any stretch — but not really so interesting, and quite often a bit tedious. And if it’s difficult but not really that interesting, and I don’t even actually need a job, why am I working so hard at this again? I couldn’t really answer that question.
  • Time is one thing you cannot buy more of. I’m getting a little old. If I wait until I’m 65 to retire, well, I might not even live that long, who knows? It’s easy to think, “Well, if I stay one more year, I can save a bit more…” But, if I can safely retire now, I figure I probably should. Tomorrow is guaranteed to no man. It will be nice to have more time to spend with family, and to do things that a job generally gets in the way of doing. If I can swing it, why not? I couldn’t think of a good reason why not.

Since I’ll be leaving California soon, and since it’s October already and the weather will be getting cold soon, especially in the mountains, I figured I should drive out to King’s Canyon and Sequoia National Parks while I still have the chance to do so easily and cheaply. So this past Sunday I loaded up the car and hit the road. I spent three nights camping there, driving around seeing the sights, and doing a bit of hiking. This turned out to be a fantastic idea, and I’m very glad I did it. Here are a few pictures from my trip to King’s Canyon and Sequoia National Parks.

So here I am, retired. Pretty strange feeling, though I’m sure I’ll get used to it. Today is the first day that has this strange kind of feeling, as it is the first weekday I’ve had where I’m just kind of sitting around the apartment, not going to work (the trip to King’s Canyon felt more like vacation, so not really so strange, just different.) Went for a walk in the early morning, trying to soak up a bit more of this fantastic crisp blue-sky California weather before I have to leave. I’ll probably spend some time playing guitar later (something I’ve neglected a bit over the past couple years) and work on Space Nerds In Space some more (also neglected over the last couple years.) I’ve given myself all this extra time, I need to be a little wary of frittering it away in meaningless ways.

“No Squandering!”