Music, software, life… and stuff.
[ Twitter ] [ GitHub ] [ Linked In ]
I had some fun today upgrading tm_interactive_input.dylib to make it work with Snow Leopard. Previously, it was busted in a pretty decent way.
I can’t be exactly sure, but it seems that malloc() on Snow Leopard calls read() for some strange reason. Since our overloaded read() implementation does quite a few things, including a lot of malloc()ing we have a problem. The end result was that anything loaded with our library injected explodes.
The solution was to use a thread local flag via the pthreads thread local storage to mark when we entered any of our overloaded code paths. This is simple enough, but I couldn’t for the life of me getting working due to a nasty issue which I hadn’t anticipated.
To use the pthread library’s thread local storage stuff, you need to create a token using pthread_key_create() which you can later use to retrieve a thread specific value for. So in C library, how do you handle initialisation code? It turns out that library constructors solve this exact problem.
News to me.
So I initialise the key in a library constructor and litter my code with the appropriate checks and so forth. No dice. I am still seeing the exact same behaviour. To make things more interesting I can’t use GDB because of the nature of the library and I can’t use printf statements because they use malloc() internally which just exacerbates the problem. I can however use write(), so that’s something.
After littering the code with write()s, I discovered that my read() implementation is being called before my library constructor. I don’t know why this is the case but I am guessing that somehow the dynamic linker has made the overloaded functions in our library available to the host binary during the loading process. Either that, or the linker itself is calling our overloaded functions. Either way, kinda strange.
Once I worked out that this was going on, it was trivial to fix. Simply set an ‘initialised’ flag in our library constructor and don’t use our overloaded functions until that is set.
GitHub has the commit for more info, or grab the binary directly (see here for install instructions).
This should be included in the next TextMate distribution.
Anyone using Mail.app to both work and home combined with MobileMe sync is probably like me and unable to avoid reading work email when at home because you just can’t resist taking a look when you see something new there. A co-worker came up with a good solution to this problem: stop Mail.app from checking for new email in your work account during non work hours.
Here is a simple AppleScript you can use to take an account out of the auto fetch schedule:
tell application "Mail" set include when getting new mail of account "account name" to false end tell
(This was inspired by Andres Almiray)
I did not have a lot of exposure to Open Source software during my formative computing years. I come from a Classic Mac OS (I saw the last few releases of 7) background and was blissfully ignorant to Linux. The move to OS X exposed me to a plethora of previously unavailable software and during this time I was becoming interested in coding. As a student surrounded by other “Computer Scientists” who were interested in anything but coding, my only real available avenue for growth was to participate in virtual communities of developers.
While it wasn’t an intentional move, the ideals and general culture of typical open source developer communities resonate very naturally with me (open information, need before greed etc). Also, I am attracted to the artistic side of writing software as opposed to just being in it for the utility. In my experience (which granted isn’t vast) you can find extremely talented people who are true artists, not just laborers, gathered around open source projects. If you are putting your work up in front of these people then you are forcing yourself to improve, and to me that is what it’s about.
I am sure not all Open Source Software is of a high calibre, but I bet you that in almost every case that man hour for man hour an open source project will trump a closed commercial project in terms of quality almost every time. If you want to improve your skills, hang out with the best around.
Apart from this self interested reason, I also enjoy creating software that other people use. There is not much better than getting an email from someone you don’t know and them thanking you for the hours you put into something because it has helped them achieve something.
I am about to commit the new GORM inspired validation mechanism to Gldapo. Here is what it is going to look like…
Instead of a DSL like GORM, we are using annotations…
import gldapo.schema.annotations. class Person { @GldapoNamingAttribute String uid @Required String sn @Required @Matches(/[A-Z]./) String givenName }
You can register your own constraints quite easily. There are two parts, the constraint annotation and the validator.
The constraint annotation (has to be in Java since you can’t define annotations in Groovy 1.5.x)…
import java.lang.annotation.*; import gldapo.schema.annotation.Validator; import gldapo.schema.attribute.validator.EqualsValidator; @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @Validator(EqualsValidator) // public @interface Equals { Object value(); }
As you can see it’s a stock standard annotation, that is itself annotated with @Validator to tell Gldapo how to validate this type of constraint.
The validator looks like this…
package gldapo.schema.attribute.validator class EqualsValidator extends AbstractFieldValidator { def validate(obj) { if (obj != this.constraint.value()) { return ['notequals', "notequals.${this.constraint.value()}"] } } }
Validators have to extend gldapo.schema.attribute.validator.AbstractFieldValidator and implement validate(obj). This method takes the value to validate and returns either a single error code, or a list of error codes. If the value is valid it should return null.
Gldapo will register several error codes if validation fails. If a class called Person has it’s name field annotated with @Equals('Luke') and it fails validation, the following error codes will be registered…
notequals
notequals.Luke
person.notequals
person.notequals.Luke
person.name.notequals
person.name.notequals.Luke
If the usage of error codes seem a bit weird here, then you should check out 7.4 Validation and Internationalization in the Grails user guide as the concept is exactly the same.
Finally, you need to register your constraint with Gldapo. You do this by listing your custom constraint types as a list under the contraintTypes key in the config…
Gldapo.initialize( contraintTypes: [Equals] )
This side of things works exactly like GORM…
def p = new Person(uid: "ld", givenName: "Luke" sn: "Daley") if (!p.save()) { p.errors.allErrors.each { println it } }
There is also the validate() method if you just want to perform validation without trying to write the object back.
If you haven’t used validation in GORM, check out this chapter in the user guide, because it will all hold true (except how constraints are defined) with Gldapo.
I am working on a grails app (more info to come), as such I am making some long needed improvements to the Grails TextMate bundle. If you are using this, you might want to subscribe to the bundle changes feed.
I have made two changes already; a snippet for the tag in GSPs, and a command to run a single test case (the currently open file in TM).