It is the weekend after BLFC. As seems to be usual for me I am just starting to feel the first signs of impending con crud in the back of my throat. I am lucky in a way. I rarely seem to get sick at the convention (with the exception of the most recent MFF, where I’d caught a cold already and likely gave it to my roommate, sorry hon). I instead tend to start picking something up shortly afterwards. Anyways, I’m getting ahead of myself so let’s start back at the beginning.

Getting There

This year I decided to try flying to the convention. I like to make plans early and months out nobody could give me a firm answer on what date they would be driving up so, to avoid the possibility of driving on my own, I reserved a seat on Alaska Airlines. The flight from San Jose is only about 50 minutes and not particularly busy so they’re flying the Bombardier Q400. This was my first time riding a turboprop and I was expecting it to feel like a small plane. In fact it didn’t feel particularly different from a jet aside from the slightly different engine noise. The ride was very smooth and takeoff was a lot faster than a larger aircraft.

View post on imgur.com

Coming out of the gate onto the tarmac is a fun experience for a transportation nerd like me. Most airports have their gates on the second floor of the terminal so it’s a long way down to reach a tiny plane like this. In the picture above, taken after landing in Reno, you can see the Grand Sierra Resort and Casino in the background under the wing. I immediately texted my friend, “Hey, I can see the con from here!”

Helping Out

Those who know me are likely aware that for the last 5 years I’ve been working in the Programming department for Further Confusion, usually as an executive lead. That position is a lot of pre-con prep work plus I’m usually running around all weekend making sure everything is going smoothly. Given that I consider FC to be my chance to give back to the community I use other conventions as an opportunity to chill out and enjoy myself. The thing is though that without something to do I tend to get bored and I’m somewhat addicted to helping out so I couldn’t resist the opportunity to help out the Registration lead with the Thursday rush. She’s a friend after all.

This kind of work is really perfect because I needed to do no prep whatsoever. I ended up working at the at-con registration booth from about 11am until 6pm. There were a lot of people coming through but we managed to get the line taken care of and it was never particularly frantic or stressful.

BLFC is using a style of badges that FC started using this year as well. Instead of a credit card sized plastic card that must be printed by a special card printer the badge material is pre-printed with one of a few badge designs. The attendee information is then printed on a transparent plastic label that is applied to a blank badge. For pre-registered attendees the labels can be printed on mass using full-sized sheets of labels in a laser printer and the badges assembled ahead of time. At-con a badge can be printed using a small label printer. The label printers are more reliable than the card printers and while this system is substantially cheaper it still has a very professional look.

I helped the FC registration lead put together some of the scripts used to print labels and I was really glad to see that BLFC had further automated the system. As a cashier I made hundreds of badges and it was incredibly easy to do. Still, at the end of the day I was tired and it was time to go and enjoy the rest of my con.

Socializing

I have a chronic problem with socializing at conventions. There are so many people around that I can easily wander around without running into anyone I know and I’m too introverted to randomly introduce myself to strangers. I have to watch out because this can very quickly put me in a sour mood. At BLFC this year the problem was exacerbated by the incredibly poor cellular and WiFi connectivity in the venue. In previous years the hotel WiFi has made up for the weak cellular signal in the lower levels but this time it actually made things worse because even though I could connect to the access point I still couldn’t get any messages through.

This is a good opportunity to plug the utility of amateur radio in this kinds of situations. I brought a bunch of radios unfortunately the folks who also had them were too busy to be monitoring the con frequency and the folks I was looking for weren’t licensed. If it’s connectivity is going to be this bad next year I’m definitely going push more friends to be on radio.

I’m not going to dwell on the down moments though. In between bouts of wondering where everybody was I got the chance to meet some great new people as well as speak face to face with folks I’d only met online. I think I went into the weekend with really high expectations and when compared against that perhaps it didn’t measure up but there was also plenty of the unexpected so I’m going to focus on that.

Finally, I really have to thank the attendees who put together room parties. It can be as much work as planning your own convention within the convention. It seemed that people had really pulled out all the stops this year and this was what really saved the social experience at this convention.

Taking Photos

Over all I didn’t take as many photos at this convention as I have at conventions past (aside from FC 2017 where I took exactly none due to staff work and forgetting my SD card at home). I think that after 7 years of conventions (FC 2010 was my first) I’m starting to be less interested in fursuits as subjects. The other issue is that the lighting in the GSR is very dark so it can be very challenging. I brought an off-camera flash as usual but still for whatever reason I wasn’t really feeling it this year so I only took about 100 exposures.

For this convention I did however, decide to try out something new and post my photos on Imgur. This seems a little more social-media friendly than Flickr and doesn’t require a Yahoo account, something I’ve been avoiding given their recently security issues. The full album is below. Leave a post in the comments if it doesn’t work properly for you.

Biggest Little FurCon 2017

Comment and share

Writing More

My friend Des recently dusted off his blog over on Dreamwidth. In a recent post Des discusses his relationship with Twitter and how it isn’t really working for them. I’m not going to summarize it here. Go open it in a new tab and read it. I’ll wait.

This post inspired me to try putting down more of my thoughts in long-form writing. While trying to fit a complete thought into 140 characters is an interesting literary challenge it is certainly not a place where I feel that I can express much nuance. On the other paw the empty buffer in my favorite text editor (vim, by the way) is certainly a daunting challenge and while many great blog entries have been written in the shower very few of them (read: none) have ever made it online.

I would like to change that, so here’s to my first post on this blog in 3 years. I recently rebuilt it with Hexo and I’m reasonably happy with how it turned out. As static site generators go Jekyll seems to be the most popular. Last time I tried to use it however I got bogged down in various Ruby issues. Between the two I’m a bigger fan of JavaScript so I chose to go with a tool built in a language I was actually familiar with.

Comment and share

Below is a piece of code similar to something I was working with last week. Please bare with me on the simplicity of this example. I know that modern applications should not use 32-bit integers to store IP addresses because of IPv6 compatibility.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
typedef struct Address {
uint32_t ip;
uint16_t port;
} Address;
typedef struct Entry {
Address address;
Connection *connection;
} Entry;
typedef struct Connection Connection;
Connection *FindConnection(const Address *address,
Entry *connections,
size_t nConnections) {
for (size_t i = 0; i < nConnections; ++i) {
if (memcmp(address,
&connections[i].address,
sizeof *address) == 0) {
return connections[i].connection;
}
}
return NULL;
}

Have you seen what’s wrong with this function? It seems simple enough. Iterate through an array of entries in some kind of connection table looking for the one with the matching IP address and port number. What could be easier? Let’s use the function now.

1
2
Address addr = { 0x7f000001, 80 };
Connection *conn = FindConnections(&addr, conns, nCons);

This code will work most of the time. To see why I said “most of the time” let’s first ask a question: What is sizeof *address in the function above? A quick test program will reveal the answer: 8

This may be a bit surprising but remember that each primitive variable type has an alignment requirement enforced upon it by the underlying architecture. A uint32_t must always have a memory address divisible by 4, a uint16_t must be at an address divisible by 2. If we construct an array of address structs in order for the the uint32_t inside of each to be aligned the compiler must add a little padding in between. Including the padding the size of the entire struct is 8. 6 bytes of data plus 2 bytes of padding. This brings us to the next question: What is the value of these two bytes? To answer this lets look at the assembly generated by the statement that initializes addr above:

1
2
movl $2130706433, -16(%rbp)
movw $80, -12(%rbp)

The variable addr consists of two values, 2130706433 (which is simply the decimal form of the hexadecimal value 7F000001) and 80. These are copied onto the function’s stack at 16 bytes before the %rbp (which is the stack base pointer) and 12 bytes before %rbp. “movl” copies 4 bytes, a “long word,” and “movw” copies 2 bytes, a word. (For the curious, on x86 8 bytes is a “quad word” and is abbreviated “q” and 1 byte is a “half word” and abbreviated “h”.) Since the struct is 8 bytes long in total we can see that it exists in the 8 bytes between %rbp-16 and %rbp-8. But wait! We’ve only copied 6 bytes! This is where the problem lies. Initializing a struct using this syntax leaves the padding bytes uninitialized. Quoting the C99 specification:

When a value is stored in an object of structure or union type, including in a member object, the bytes of the object representation that correspond to any padding bytes take unspecified values.

Now we understand why this code doesn’t work sometimes. C doesn’t guarantee anything about the padding bytes but in the memcmp call we compare the entire struct, including the padding. Since the padding is uninitialized it could be any two random bytes that happened to be there when the variable was initialized. Most of the time they will be zero but every once in a while they will be something else and the code will mysteriously fail to find a connection entry which may otherwise appear to be present.

How can we catch this before it causes random failures? Running the program under a memory checker such as Valgrind will alert you to comparisons which use uninitialized values. Here’s what the failure looks like:

1
2
3
4
Conditional jump or move depends on uninitialised value(s)
at 0x4C2EB32: bcmp (mc_replace_strmem.c:930)
by 0x400602: FindConnection (test.c:19)
by 0x4006A7: main (test.c:37)

Valgrind is complaining here that bcmp (which is the function behind memcmp above) is branching based on an uninitialized value. While it causes your application to slow down by a factor of 10 or more Valgrind is a very useful tool for detecting silent errors that may become bugs in the future.

How could we avoid this problem? The first answer is that maybe using memcmp wasn’t a good idea. As we’ve seen using it this way makes some assumptions about how the compiler is laying out memory that might not hold true in all circumstances. Explicitly comparing the IP and port fields will generate the correct code and may actually be faster since it isn’t calling a generic function like memcmp. Another way to avoid this is to make the padding bytes explicit like this:

1
2
3
4
5
typedef struct Address {
uint32_t ip;
uint16_t port;
uint16_t padding;
} Address;

Why does this make a difference? First, the structure is still 8 bytes. All of the uint32_t’s can easily fall on 4 byte boundaries and uint16_t’s on 2 byte boundaries. Does the initialization style we used above still work? Yes. C allows struct initialization to omit some fields. In fact, it does exactly what we want.

If there are fewer initializers in a brace-enclosed list than there are elements or members of an aggregate, or fewer characters in a string literal used to initialize an array of known size than there are elements in the array, the remainder of the aggregate shall be initialized implicitly the same as objects that have static storage duration.

The language is a little convoluted but “objects that have static storage duration” are initialized to zero so our unlisted padding field will be zeroed as well. Let’s check out the assembly again to be sure.

1
2
3
movq $0, -16(%rbp)
movl $2130706433, -16(%rbp)
movw $80, -12(%rbp)

This isn’t exactly what I was expecting but it makes sense. By writing zero as an 8-byte value over the entire variable each field is initialized to zero. Then the two fields we have explicitly given values to are set as before.

What is the lesson to be learned here? C gives the programmer almost complete control over almost all of the low level details of the system executes their code but this control comes at a price. The programmer must understand how the low level details work or else code which, at a high level, seems to be correct may not do what they intend.

Comment and share

After fighting with TweetDeck to post a picture: Why can’t I drag-and-drop it into the compose widget? Why must I manually resize it so that it’s under 3MB? I decided it might be time to choose a better Twitter client. This brings me around to TweetBot.

As far as I can tell TweetBot is the best Twitter client available for OS X. It supports the feature for which I use TweetDeck over Twitter’s offical client: multiple columns. The one sticking point for me is the price. Compared to every other Twitter app I’ve used, which were free, TweetBot costs infinitely more: $19.99. In the grand scheme of my budget though $20 isn’t very much but I tend to give a reasonable amount of thought to non-food items that cost more than a few dollars so here are some things I compared it to:

  • Dinner out at a restaurant can easily approach or exceed $20 including tax, tip, beverages and appetizers.
  • If I’d bought TweetBot when I first started using Twitter I would have paid, on average, half a cent for each of my 3,875 tweets.
  • Based on download size TweetBot is $3.77 per MB, compared to $0.34 per MB for one of my employer’s products.
  • A new release on iTunes is also usually around $19.99. In comparison I will probably spend more than 120 minutes paying attention to TweetBot.

I could keep going like this but the comparisons would begin to get silly. In the end I’m going to buy TweetBot. I think the point of this story is that it’s pretty hard to decide on the value of a software program. App stores these days tend to sell things for either free, cheap (1¢ — $2) or expensive (more than $2) compared to old-fashioned boxed software which I recall usually started at $20 and sometimes made it to the bargain bin at $5 — $15. On top of this, if I pay $19.99 for TweetBot now they will never get another cent from me because the Mac App Store doesn’t (currently) charge for updates. Heck, Apple released OS X Mavericks, the product of tens of thousands of man-hours of work (at least), for no cost what-so-ever.

With all of this in mind all I can say is that I have no idea how much software is really worth.

Comment and share

  • page 1 of 1
Author's picture

binaryfox

author.bio


author.job