Tried to upgrade node from 0.4.5 to 0.6.x and my my micro kept falling over dead. I know it's an edge case, but it's an annoying set of symptoms that I figured I should post in case someone else runs into the same issue.
tl;dr => It's not a node problem its an AWS kernel issue with old AWS AMIs and Micro instances
So I have a micro that's about a year old, i.e. beta AWS-AMI, but i gather the same problem happens with pretty much every AMI prior to 2011.09. I was running node 0.4.5, but had started using 0.6.4 on my dev and some modules were now dependent on it. Since micro instances go into throttle mode when building anything substantial, i hope to use the build from my dev server. The dev machine is centos, so i crossed my fingers, copied the build over and ran make install. No problem. Then i tried npm install -g supervisor and it locked up. Load shot up, the process wouldn't let itself be killed and i got a syslogd barf all over my console:
Message from syslogd@ at Wed Dec 28 00:58:19 2011 ... ip-**-**-**-** klogd: [ 440.293407] ------------[ cut here ]------------ ip-**-**-**-** klogd: [ 440.293418] invalid opcode: 0000 [#1] SMP ip-**-**-**-** klogd: [ 440.293424] last sysfs file: /sys/kernel/uevent_seqnum ip-**-**-**-** klogd: [ 440.293501] Process node (pid: 1352, ti=e599c000 task=e60371a0 task.ti=e599c000) ip-**-**-**-** klogd: [ 440.293508] Stack: ip-**-**-**-** klogd: [ 440.293545] Call Trace: ip-**-**-**-** klogd: [ 440.293589] Code: ff ff 8b 45 f0 89 .... ip-**-**-**-** klogd: [ 440.293644] EIP: [] exit_mmap+0xd5/0xe1 SS:ESP 0069:e599cf08
So i killed the instance. Figuring it was config diffs between centos and the AMI, i cloned my live server and fired it up as a small to get decent build perf. Tested 0.6.4, all worked, brought it back up as a micro and, blamo, same death spiral. Back to small instance, tried 0.6.6 and and once again as a small instance it worked, but back as a micro it still had the same problem.
Next up was a brand new AMI, build node 0.6.6 and run as micro. Everything was happy. So it must be something that's gotten fixed along the way. Back to the clone and yum upgrade. Build node, try to run, death spiral. Argh! So finally i thought i'd file a ticket with node.js, but first looked through existing issues and found this:
Node v0.6.3 crashes EC2 instance
which pointed me at the relevant Amazon release notes which had this bit in it:
After using
yumto upgrade to Amazon Linux AMI 2011.09, t1.micro 32-bit instances fail to reboot.
There is a bug in PV-Grub that affects the handling of memory pages from Xen on 32bit t1.micro instances. A new release of PV-Grub has been released to fix this problem. Some manual steps need to be performed to have your instance launch with the new PV-Grub.
As of 2011-11-01, the latest version of the PV-Grub Amazon Kernel Images (AKIs) is 1.02. Find the PV-Grub AKI's for your given region by running:
ec2-describe-images -o amazon --filter "manifest-location=*pv-grub-hd0_1.02-i386*" --region REGION.Currently running instances need to be stopped before replacing the AKI. The following commands point an instance to the new AKI:
ec2-stop-instance --region us-east-1 i-#####
ec2-modify-instance-attribute --kernel aki-805ea7e9 --region us-east-1 i-#####
ec2-start-instance --region us-east-1 i-#####.If launching a custom AMI, add a
--kernelparameter to theec2-run-instancescommand or choose the AKI in the kernel drop-down of the console launch widget.
Following these instructions finally did the trick and 0.6.6 is happily running on my old micro instance. Hope this helps someone else get this resolved more smoothly.
I consider the start of my programming carreer to be when I learned Genera LISP on Symbolics LISP machines. Sure I had coded in Basic, Pascal and C, and unfortunately Fortran, before this, but it had always just been a hobby. With LISP, I got serious about languages, algorithms, etc.
Genera LISP had its own object system called Flavors, much of which eventually made it into CLOS, the Common Lisp Object System. Flavors had capabilities called Wrappers and Whoppers, which provided aspect oriented capabilities before that term was even coined. Both achieved fundamentally the same goals, to wrap a function call with pre and post conditions, including preventing the underlying function call from occuring. Wrappers achieved this via LISP macros, i.e. the calls they wrapped were compiled into new calls, each call using the same wrapper sharing zero code. Whoppers did the same thing except dynamically, allowing the sharing of whopper code, but also requiring at least two additional function calls at runtime for every whopper.
So what's all this got to do with javascript? Well, yesterday I got tired of repeating myself in some CPS node coding and just turn my continuation into a new continuation wrapped with my common post condition, and so I wrote the Whopper capability for javascript. But first a detour through CPS land and how it can force you to violate DRY.
So in a normal synchronous workflow you might have some code like this:
function getManifest(refresh) {
if(!refresh && _manifest) {
return _manifest;
}
var manifest = fetchManifest();
if(!_manifest) {
var pages = getPages();
_manifest = buildManifest(pages);
} else {
_manifest = manifest;
if(refresh) {
var pages = getPages();
updateManifest(pages);
}
}
saveManifest(manifest);
return _manifest;
};
But with CPS style asynchrony you end up with this instead:
function getManifest(refresh, continuation, err) {
if(!refresh && _manifest) {
continuation(_manifest);
return;
}
fetchManifest(function(manifest) {
if(!_manifest) {
getPages(function(pages) {
_manifest = buildManifest(pages);
saveManifest(_manifest,function() {
continuation(_manifest);
});
}, err);
return;
}
_manifest = manifest;
if(refresh) {
getPages(function(pages) {
updateManifest(pages);
saveManifest(_manifest,function() {
continuation(_manifest);
});
}, err);
} else {
saveManifest(_manifest,function() {
continuation(_manifest);
});
}
}, err);
};
Because the linear flow is interrupted by asynchronous calls with callbacks, our branches no longer converge, so the common exit condition, saveManifest & return the manifest, is repeated 3 times.
While I can't stop the repetition entirely, I could at least reduce it by capturing the common code into a new function. But even better, how about I wrap the original continuation with the additional code so that I can just call the continuation and it runs the save as a precondition:
function getManifest(refresh, continuation, err) {
if(!refresh && _manifest) {
continuation(_manifest);
return;
}
continuation = continuation.wrap(function(c, manifest) { saveManifest(manifest, c); });
fetchManifest(function(manifest) {
if(!_manifest) {
getPages(function(pages) {
_manifest = buildManifest(pages);
continuation(_manifest);
}, err);
return;
} else {
_manifest = manifest;
if(refresh) {
getPages(function(pages) {
updateManifest(pages);
continuation(_manifest);
}, err);
} else {
continuation(_manifest);
}
}, err);
};
What makes this capture possible is this extension to the Function prototype:
Object.defineProperty(Function.prototype, "wrap", {
enumerable: false,
value: function(wrapper) {
var func = this;
return function() {
var that = this;
var args = arguments;
var argsArray = [].slice.apply(args);
var funcCurry = function() {
func.apply(that, args);
};
argsArray.unshift(funcCurry);
wrapper.apply(that, argsArray);
};
}
});
It rewrites the function as a new function that when called will call the passed wrapper function with a curried version of the original function and the arguments passed to the function call. This allows us to wrap any pre or post conditions, including pre-conditions that initiate asynchronous calls themselves, and even lets the wrapper function inspect the arguments that the original function will be passsed (assuming the wrapper decides to call it via the curried version.
continuation = continuation.wrap(function(c, manifest) {
saveManifest(manifest, c);
});
The above overwrite the original continuation with a wrapper version of itself. The wrapper is passed c, the curried version of the original function and the argument that continuation is called with, which we know will be the manifest. The wrapper in turn calls the async function saveManifest with the passed manifest and passes the curried continuation as its continuation. So when we call continuation(_manifest), first saveManifest is called which then calls the original continuation with the _manifest argument as well.
This isn't a review of the conferences as much as my impression of the different forces acting upon javascript, the language. Before I start, i should get my bias out of the way, as it likely colors my observations: Like many I came to javascript out of nessessity and seeing a C-like syntax tried to make it fit into a mold it was ill-suited for and much frustration ensued. I've taken the language at face value, and being a fan of expressions and lambdas, have found it to be fun and flexible. That said, it does have some well documented warts and in many ways these warts are what are behind the different forces pulling at the language.
jsconf and nodeconf had significantly different vibes, but where I had expected the difference to be due to server vs. client people, it seemed that the difference was more closely aligned to the relationship the attendees had to javascript. My impression is that jsconf is a community brought together by the common goal of creating amazing experiences in the browser. Some embrace the language as is, others rely on frameworks (or this year's hottness, micro-frameworks) to make them productive, while yet others try to bend the language to their will by using javascript as a compilation target.
Of those using javascript as a compilation target, coffeescript was the clear star, with enough talks using it as their defacto language that got the impression that it was a natively supported language. The next to last #jsconf talk featuring @jashkenas even nullified the B Track entirely and was joined by @brendaneich to talk about JS.Next. The talk covered proposed and accepted changes to javascript, and coffeescript was held up as testbed for fast prototyping and experimentation with possible syntax changes
The final jsconf talk was clearly meant to come off as a Jobsian lead-in to a big reveal. This reveal was traceur, google's transpiler for trying out what google wants JS.Next to look like. I don't know whether it was the relatively stilted presentation style or the fact that it re-hashed a lot of Brendan's presentation, but the crowd lacked enthusiam for both the presentation and the reveal. I personally liked what they were proposing, but I can't say I disagree with one attendee later describing it as having a condescending tone, something like "we're here to rescue you from javascript". Brendan seemed to have read the talk this way as well.
All in all, jsconf clearly seemed to be celebrating the possibilities ahead and the power of the language to be mutated into virtually any form. More than once I overhead someone say that they were sold on coffeescript and would try it for their next project.
The following night was the the nodeconf pre-party. I had the pleasure of talking extensively with @izs (of npm fame) and @mikeal about various topics javascript and node. Being the language geek that I am, I brought up traceur and coffeescript and was quick to realize that this was a different crowd than jsconf: Nodeconf is a community that chose javascript as their primary language, finding it preferable to whatever language they had worked with before. Clearly the node community does not need language changes to enable their productivity.
This impression of a community happy with the state of their chosen tool was re-enforced throughout the next day at nodeconf. One talk on Track A was "Mozilla Person, Secret Talk". When I suggested that it would likely be about Mozilla's efforts to create node on top of spidermonkey one of the guys at our table said that if that was the case, he would have to go and check out Track B. As the Mozilla person turned out to be Brendan, our tablemate did leave. The talk itself was briefly about V8Monkey and SpiderNode, the two abstraction layers Mozilla is building to create a node clone, and largely a re-hash of Mozilla's JS.Next talk. The post talk questions seemed generally uninterested in JS.Next and were mostly different forms of "what do we have to gain from SpiderNode."
Clearly the node community is not beholden to any browser vendor. They've created this new development model out of nothing and are incredibly productive in that environment. The velocity of node and the growth of the npm ecosystem is simply unmatched. What node has already proven is that they don't need rescuing from javascript as it stands. Javascript is working just fine for them, thank you.
I do believe that Javascript is at a cross-roads, and being the only choice available for client-side web development, it is being pulled into a lot of directions at once by everyone wanting to influence it with bits from their favorite language. It is clear that JS.Next is actually going to happen and bring some of the most significant changes the language has seen in an age. I can't say I'm not excited about the proposals in harmonizr and traceur, but I certainly can understand why this looming change is seen as a distraction by those who have mastered the current language. Being more of a server-side guy nodeconf was clearly my favorite of the two conferences and while I had started the week in Portland with the intention of writing my future node projects in coffeescript, I've now decided to stick with plain old javascript. I fear not doing so would only lead me back into my original trap of trying to make the language something it wasn't which in the end would only hurt my own productivity.
It's the beginning of a new year and you know what that means: Public disclosure of measurable goals for the coming year. I've not made a New Year's Resolution post before, which of course means that not living up to them was slightly less embarrassing. Well, this year, I'm going to go on the record with some professional development goals. I consider the purpose of these goals to be exercises of taking myself out of my comfort zone. Simply resolving to do something that is a logical extension of my existing professional development road map is just padding. But before I get into enumerating my resolutions for 2011, let's see how I fared on those undisclosed ones from last year.
By the end of 2009, I had only used git to the minimum extend required to get code from github. I knew i didn't like svn, because I was a big branch advocate and it just sucked at all related tasks, like managing, merging, re-merging, re-branching branches. I had been using perforce for years and considered it the pinnacle of revision control because of its amazing branch handling and excellent UI tooling. I also got poisoned against git early when I watched Linus assigned the sins of svn to all non-distributed version control system in his googletalk on git. I knew this was irrational and eventually i would need to give git a chance to stand on its merits. But the only way that was going to happen was by going git cold turkey and forcing myself to use it until i was comfortable with it. That happened on January 1st, 2010. I imported all my perforce repos into git and made the switch. I also started using git on top of all projects that were in svn that i couldn't change, keeping my own local branches and syncing/merging back into svn periodically. This latter workflow has been amazingly productive and gives me far greater revision granularity, since i constantly commit WIP to my local branches that wouldn't be fit for a shared SVN trunk.
One other aspect about DVCS that had kept me from it was that I consider version control both my work history and my offsite backup. So, I probably still push a lot more than most git folks. Sure, i've only lost work once due to disk failure vs. several times because of ill-considered disk operations or lack of appropriate rollback points, but I also work on a number of machines and religious pushing and pulling lets me move between machines more easily. Basically, I never leave my desk without committing and pushing because I've been randomized by meetings or other occasions that led me home before making sure i had everything pushed for work from home.
After a year, I can safely say, i'm not looking back. Git has spoiled me and I even use it for keeping track of CM changes for this and other blogs.
The last couple of years I've been doing toy projects in Ruby as an alternative to my daily C# work. But unlike seemingly everyone else, i never found it to be more fun than C#. Maybe it's because i used to be dynamic language guy doing perl and I became a static typing guy by choice. As dynamic languages go, Ruby doesn't really buy me anything over perl, which I'd worked with off and on for the last 15 years. And while the energy of the Ruby community is amazing, too much of that energy seems to be devoted to re-discovering patterns and considering them revolutionary inventions.
Javascript, on the other hand, offered something over C# other than just being a dynamic language. It was a language that could be used efficiently on both client and server. That was compelling (and was the same reason why I liked Silverlight as a developer, although i never considered it viable for use on the web). Up until last year, I used javascript like so many server-side programmers: only in anger. I knew enough to write crappy little validation and interactivity snippets for web pages, but tried to keep all real logic on the server where i was most comfortable. When i did venture into javascript, I'd try to treat it like C# and hated it even more because I perceived it to be a crappy object-oriented language. But even then I understood that what I hated more than anything was the DOM and its inconsistencies and that blaming javascript for those failures was misguided.
So in 2010 I was going to get serious about javascript and but initially went down the frustrating path of trying treat javascript like other OO languages I knew. It wasn't until I watched Douglas Crockford's InfoQ talk "The State and Future of Javascript", that it clicked. What I called object-oriented was really a sub-species called class oriented. If I was to grok and love javascript, i needed to meet it on its own turf.
In the end, 2010 never went beyond lots of reading, research and little toy projects. I should have committed to solving a real problem without flinching. While my understanding of javascript is pretty good now on an academic level, i certainly didn't get serious.
It wasn't as much a new lesson learned as a re-affirmation of an old axiom: Learning something to the extend that you can truly judge its merits and become more than just proficient requires immersion. Casual use just doesn't build up the muscle memory and understanding required to reason in the context of the subject. If you don't immerse yourself, your use of that subject will always be one of translation from your comfort zone into the foreign concept, and like all translations, things are only likely to get lost in the process.
If you’ve had the misfortune of mentioning AJAX in my presence, then you’ve heard me rant about the crappy user experience we are all willing to accept in the name of net connectness. This really is a lamentation about the state of Rich Internet Application Frameworks and my dislike for coding in Javascript. Well, it looks like there are more choices than I’d been aware of (the choice of google search terms makes all the difference). Still not what I’d hope, but at least its getting more digestible.
Programming based on the AJAX technique has certainly done much to elevate the quality of web apps, but I still feel they are always just a pale facsimile of good old desktop apps. Even the best webapp UI is generally great “for a webapp”. However lots of libraries are emerging, as are s number of widget sets, so that’s definitely improving. While most toolkits let you extend them, you’re always doing your server in one language and your custom UI in javascript.
What I personally have hoped for was a VM in the browser that was addressable by a number of compilers creating bytecode. Everytime I see a platform that runs a VM underneath and doesn’t let you address that VM directly, I feel like a great opportunity has been missed. Oddly, MS’ CLR is the best example of a VM that lets you address it in virtually any language. They certainly didn’t invent the concept but they’ve promoted it. I think Sun did a major disservice to itself and VMs in general when they married Java the language, the Virtual Machine and the Religion into a single marketing entity. I mean who even knows that there are lots of languages that can be used to target the JVM?
A while ago I found a post by Brendan Eich talking about the future of the Mozilla VM and mentioned mono and the jvm as options. Yesterday, he posted about open web standards and I seized the opporunity to ask about bytecode addressability of JS2′s VM. His answer about legal issues is likely a big reason why mono was abandoned as an option:
“there won’t be a standard bytecode, on account of at least (a) too much patent encrustation and (b) overt differences in VM architectures. We might standardize binary AST syntax for ES4 in a later, smaller ECMA spec — I’m in favor.”
But as he also pointed out there is always compiling to Javascript instead of bytecode. The options he and another poster mentioned were:
Of the three I initially liked the Morfik approach the best, but doing a bit more research, they seem to be well on the path of propagating the same patent issues that Brendan Eich attributes the lack of standard VMs to. Pity.
Looking around for Javascript compiler’s I noticed that this approach is also under development at MS as Script# although it hasn’t yet moved up to an official MS project. Interestingly this does pit MS vs. Google once again, framed in a C# vs. Java context with ASP.NET AJAX w/ Script# and GWT. And if there’s anything that’s just as great for innovation as open standards, in my opinion, it’s competition between giants. I look forward to seeing them try to outdo each other.
So far, we’re stuck in the browser, and even with tabs, I sure hope this isn’t the future of applications. If we are to move beyond browser, what are our options?
Clearly, Adobe is leading the RIA platform wars with Flash and with Flex, SWF certainly looks more like a platform than an animation tool forced to render User Interfaces.
And Apollo certainly looks to push Flash as a platform as well as making it a stand-alone app platform. I certainly think this is going to be the juggernaut to beat. Given my dislike for the syntax of (Java|Ecma|Action)Script, it’s unlikely to be my platform of choice. And i don’t see a Adobe supporting cross-language compilation and support for Eclipse or Visual Studio at the expense of their Dev suite.
I really like the concept of WPF. It’s philosophy is what I want the future to look like. Mark-up and code separate, common runtime addressable in many languages on client and server, well developed communications framework. Ah, it warms my heart.
But, a) it’s closed, b) it’s only Windows (i’ll get to WPF/E in a sec) and c) boy, is it over-architected. Now, it’s at 1.0 release and if there’s anything about MS releases, they seldomly get it right in 1.0. We’ll see what 2.0 looks like.
WPF/E looks like a combination of simplifying WPF (is this 2.0?) and going after Adobe. And with Script# and recent admissions of some type of CLR on Mac for WPF/E, we’re looking at a trojan horse to get Rich Internnet Application Development in .NET established in both the browser and the desktop across platforms. Unfortunately, “across platforms” for MS still means Windows and Mac, while Adobe’s Flash 9 has demonstrated their dedication to encompass the linux sphere as well. I don’t think that’s going to change… I just don’t see MS going to linux with the CLR and I find the likelyhood of them leveraging mono‘s efforts just as unlikely. I wouldn’t mind being wrong.
This isn’t a platform per se, but I’ve seen a lot of cool tech demo’s using XUL and/or the canvas tag. Also looking at the work that Micheal Robertson’s AJAX13 has done, I think there are the makings of a stand-alone app platform here. If your runtime requirements are “install firefox, but you don’t even have to use it as your browser if you don’t want to”, that’s a pretty small barrier for a platform that runs everywhere. Personally, I hope someone straps mono or the recently liberated jvm to XUL and builds a platform out of it (you’d get mature WS communication for free with either), because of all the options that looks the most appealing to me personally.
Considering that GWT and Script# had eluded my radar up until today, I’m sure there’s even more options for RIA’s out there. I just hope that people developing platforms take the multi language lessons of the legacy platforms to heart. All the successful OS’s of the past offered developers many ways of getting things done. You looked at your task, picked the language that was the best fit to the task and your style of programming and you delivered your solution. VMs have shown that supporting many languages in an OS independent way is viable, so if you’re building a platform now, why would you choose to mandate a language and programming model. I sure hope that the reason for not going this route isn’t going to be “because the patent system is stopping me” — that would be the ultimate crime of a system that was supposed to foster innovation.
I’ve recently been doing javascript coding again. Being the object bigot that I am, everything that interacts with a DOM element gets wrapped in an object that becomes responsible for that element’s behavior. Well, then i tried to move all the event handler code from the procedural side to the object side and things broke, and hard.
At first I was confused why it wouldn’t call my this._InternalMethod inside my event handler. Then I remembered that i’ve been spoiled by the CLR and that I was dealing with plain old function pointers, not delegates.
While the Atlas framework provides delegate functionality (along with a lot of other useful things), this was not for a .NET 2.0 project and I didn’t want to graft the Atlas clientside onto it as a dependency. But knowing that Atlas does delegates, i knew it was possible.. but how?
I found the answer in this article which basically uses closures in javascript to allow the persistent of the object context in event handlers.
So basically to create an event handler that maintains its object context do this:
function MyObject = function(name)
{
this._name = name;
var _this = this;
this.MyEventHandler = function()
{
alert("My name is "+_this._name;
}
}
Great. Now I can avoid all procedural code and just have my object subscribe themselves to element and document events and handle them in their own context
The clip attribute in CSS is not what I would call the simplest to understand. Never mind that the rect() function uses a space separated list instead of a comma separated one, but that some browsers still understand comma separated. But the ordering of the clip rect of top right bottom left is just bizarre. Finally to understand what clipping does, it’s important to realize that the clip rect defines a rectangle of what will be shown, defined from the origin, but it does not affect positioning of the image, which still starts at the origin, clipped areas not withstanding.
Since i’ve done this too much over the last week by trial and error, i decided to just put together a quick page illustrating clip usage.
Working on a little example of panning images with javascript. So far it doesn’t do image boundary detection. It also just pans one large image, not a tiled and continously loading set, like Google Maps.
Had some fun this weekend playing with Javascript, trying draw dynamic lines. Since Javascript doesn’t actually have any kind of Draw() or Paint() methods, it comes down to manipulating images. I originally started by scaling images of lines, but even after adding a bunch of variations of lines for different lengths and angles, it always looked damn ugly.
Finally I decided to go the traditional line drawing way: One pixel at a time. Well, almost.. i have tiny segments with lovely alpha blurred edges and created them in horizontal, vertical and the two diagonal variations. And i create dashed lines from them, calculating points along the line.
The current state of this experiment can be found here. (Note: This does not work in IE right now. Really only because i didn’t put in the alternate code for finding the mouse coordinates, so i’ll fix that in time).
Next, time to play with XmlHttp and generate finalized line segments on the fly and place them, as well as save the information so you can recall the paths drawn. Then, I’ll look into emulating the google maps code for panning the background around and bringing in offscreen content on the fly.
So a while back I read an an article about the Client Callback Feature in ASP.NET 2.0, which allows ASP.NET 2.0 to do updates to a page without a full page rountrip to the server. But wouldn’t you know it, it was specific to Internet Explorer. The article ended on a hopeful note with:
Please note that not every browser supports client callbacks, so two new boolean properties named SupportsCallback and SupportsXmlHttp were added to the Request.Browser object. Currently, both properties will return the same value, but the two properties were created because client callbacks might be implemented using a different technique other than the XMLHTTP ActiveX object in the future.
2.0 is still not out, but cross-browser support using XMLHttpRequest is certainly possible to anyone wanting to roll their own code. A very nice example of this can be found here.
ASP.NET 2.0 isn’t out yet. So i figured, i might as well see if the stance for Client Callbacks and cross-browser support has changed since that first article. Info was only vague, but i think the answer is indeed maybe? — at least if this blog post is favorably interpreted… Although this blog did not interpret it as such…
If it’s not in there, I’m sure going to find out how hard it would be to subclass the appropriate classes to create a W3C XMLHttpRequest capable version