Search this site

Metadata

Articles

Projects

Presentations

keynav with xinerama support

This is the same post I made to the keynav-users mailing list

I just finished working on the xinerama portion of multi-screen support for keynav.

If someone is interested, I could use some help testing. It's working for me, and there are a few odd behaviors that I'm not sure are the best. Let me know if you test it.

No new official release yet, but if you want to test, svn can be fetched with:
svn checkout http://semicomplete.googlecode.com/svn/keynav

- Include support for multiple screens.
  * When 'start' happens, the region will be the size of the current display
    (wherever the mouse is)
  * Moving the region outside of the current display will move it to the next
    display (right or left). This currently only works with Xinerama.
  * History works as expected (move to the right display, history-back goes to
    the previous display, etc)
  * When multiple Screen (non-xinerama) are found, XGrabKey on all root windows.
  * Screens are sorted, if possible, from left-to-right based on x-coordinate
    origin. This unfortuntely means, for now, only left-to-right monitor
    configurations are known to be supported.

keynav in Xinerama

I've got a dual-head setup now that has unequal resolutions. Keynav kind of sucks when this situation occurs, so I'm adding multiple-screen and Xinerama support to keynav. I'll update here when it's done.

My beloved Voodoo 3

Tonight, in preparation for getting a second monitor at home, I swapped out my trusty Voodoo 3 2000 video card for a newer Geforce 6200 (stolen from a workstation I wasn't using anymore) which has dual outputs. While doing this, it occurred to me that this video card was the only piece of pre-college computer hardware I still had.

Part of me is sad to see it go.

My ensuing battle with ubuntu to get the @#%$ing nvidia drivers to work definitely ranks in my top 10 linux battles. I think I eventually resolved the problem by applying the monte carlo method (*) to apt-get invocations and downloaded the latest driver from nvidia myself, which failed compile many times until I again applied the monte carlo method to make targets in the kernel source (make oldconfig prepare scripts something something?). I remember something about the apt mirrors no longer having anything resembling my kernel version so installing the 'restricted' modules wasn't an option until I randomly updated 'linux-image'. "Image" obviously means "kernel and initrd friends" :(

I'll miss you, Voodoo 3.

(*) Turns out 1000 monkeys with 1000 typewriters will eventually get nvidia drivers working in ubuntu.

libevent bufferevevents on pipe(2)

From the libevent documentation:
A new bufferevent is created by bufferevent_new(). The parameter fd specifies the file descriptor from which data is read and written to. This file descrip- tor is not allowed to be a pipe(2).
It says it's not allowed to be a pipe, but it works just fine in Linux with epoll, poll, and select.

I'm certain I've just unleashed some evil demons that'll make my code crash in unexpectedly wonderful ways as a result... ;)

Watching process output with libevent

I started really learning libevent today. The API docs for libevent are pretty good, but I'm having trouble finding good examples that use it. To that end, I'll provide my own. This one uses a bufferevent to watch stdout on a child process.

Code: libevent-execwatch.c

Grok (pcre grok) nested predicates

I've spent the past few days refactoring and redesigning some of grok (the C version). Some of the methodology was using lazy test-driven design (writing tests in parallel, rather than before), which seemed to help me get the code working quicker.

We can now nest predicates, so you could ask to match an ip or host which has a word in it that matches 'google'. This example is a little silly, but it does show nested expressions.

% echo "www.cnn.com something google.com" \
  | ./main '%{IPORHOST=~/%{WORD=~,google,}/}' IPORHOST
google.com
I switched away from using tsearch(3) and over to using in-memory bdb; I've been happy ever since. Predicates can now live in an external library in preparation for allowing you to write predicates in a scripting language like Python or Ruby.

I'm using CUnit plus a few script hacks to do the testing. It's working pretty well. I have a few hacks (check svn for these), but the results look like this:

% make test
  Test: grok_capture.test.c:test_grok_capture_encode_and_decode ... passed
  Test: grok_capture.test.c:test_grok_capture_encode_and_decode_large ... passed
  Test: grok_capture.test.c:test_grok_capture_get_db ... passed
  Test: grok_capture.test.c:test_grok_capture_get_by_id ... passed
  Test: grok_capture.test.c:test_grok_capture_get_by_name ... passed
  Test: grok_pattern.test.c:test_grok_pattern_add_and_find_work ... passed
...

libc's tree functions, function pointers, and bdb.

Whoever wrote the tsearch/tfind/tdelete/twalk functions for libc clearly stopped thinking about how it would be used. The only way I can see to iterate the tree is to use twalk, which doesn't let you pass any extra arguments to your provided action method.

This sucks if, for example, you wanted to get a list of all entries in the tree in a threadsafe or multiplicity-safe way.

Some workarounds include:

  • Every time you insert, add the same structure to an array.
  • Use something that supports sane iteration (bdb, for example).
I looked into using bdb for some things, but the tree I wanted to iterate over most was a structure that held, among other things, a function pointer. Function pointers are magical and special and are held in a place in memory you can't simply make a copy of. If you try to store a function pointer in an in-memory BDB database, the value that comes out of your query will be different than the function pointer.

This bdb code sample attempts to store a function pointer in bdb. The output is:

stored: 607a70
actual: 4005e8
The value changed because copying a function pointer doesn't work.

There's a workaround here that might be useful - dlopen(). Any functions I want to store in bdb, I would store by string name and fetch the function pointer with dlsym().

This dlopen example shows how to dlopen yourself and fetch a function by string name.

Fun with pointers.

Revision 2000

I spent some time putting love into cgrok (uses libpcre) tonight.
  • Logging facility to help in debugging. Lets you choose what features you want logging (instead of lame warn/info/number log levels)
  • Added string and number comparison predicates
  • Wrote a few more tests which uncovered some bugs
I also broke 2000 revisions in subversion. Yay.
Sending        test/Makefile
Transmitting file data .
Committed revision 2001.

Sysprep may cause early balding.

I was happily moving along doing windows automation tonight, when suddenly sysprep broke. I'm sure I killed it by accident, or something. Googling around for the error found this knowledgebase article explaining that there is no way to recover and, quote, "When you experience this error, you must re-create the image. You cannot correct the problem with the image."

Fuck that.

If you read the docs on using sysprep/wsim/windows aik/whatever, they all point you at building a 'reference computer' which entails lots of manual work modifying settings and installing things. Sysprep can make useless all of your precious work? Sweet!

I'm just glad most of the things I've done to this system were automated so I can just reinstall and rerun the scripts.