Here is a neat trick. If you want to start a program that always respawns if it gets killed, just put it in /etc/inittab. The init process will respawn the program. That's what it's for.

Here's an example. Let's say you want /bin/unkillable to always run. Put this in /etc/inittab:

uniq:3:respawn:/bin/unkillable

Then run init q to make init re-read the inittab file. Now whenever /bin/unkillable gets killed, init will respawn it.

The init process uses this same trick to spawn terminals (otherwise if the terminals died and no one respawned them, no one would be able to log in from the physical terminals). This approach is also very useful if you absolutely must have some programs running. You don't even need complicated tools such as daemontools or supervisor to respawn programs. In most cases this trick is enough.

More information about init and /etc/inittab can be found in man init and man inittab. Until next time.

Footnote:
* by unkillable I mean one that respawns when you kill it.

This is going to be a super quick tutorial about how to access a Windows environment through ssh.

Step 1. Install cygwin, and make sure openssh and cygrunsrv packages are installed:


Make sure openssh is selected for installation


Make sure cygrunsrv is selected for installation

Step 2. Start cygwin and run ssh-host-config to configure ssh:


Run ssh-host-config to configure ssh

Step 3. Run cygrunsrv -S sshd to start sshd as a Windows service:


Run cygrunsrv -S sshd to start sshd

Step 4. Ssh into Windows using your favorite ssh client


Use putty to ssh into Windows

You can even set this up for your local workstation (if it happens to be Windows). Then you can forget about cmd.exe or PowerShell and use a real shell locally. Until next time.

Here's another interesting story about type of problems we've to deal at Browserling and Testling. This story is about how we implemented Windows user session cycling for Testling.

Here's what it is.

We run JavaScript tests on Windows for days straight and Windows sessions become really unstable after a while. When that happens we start getting errors such as Internet Explorer timing out randomly although everything is fine:


Internet Explorer cannot display the website

Or remote desktop connection gets messed up and I'm no longer able to get into the server:


Remote Desktop can't connect to the remote computer

Or Chrome starts to randomly crash:


Aww snap

None of these errors happen when the Windows session is fresh, so to work around these issues we implemented a Windows session cycler that simply logs out the user that runs tests, and logs it back in again every 6 hours. The implementation is pretty straight forward and just uses the standard Windows command line tools for managing users, such as users.exe and logoff.exe, as well as rdesktop.exe.

The user cycler is about a 100 line program but here's how it basically works:

user_id = find user id of testling user using users.exe
call <logout.exe user_id>
wait until user has been logged off
login testling user again using rdesktop.exe

The testling user's startup script initializes the testing environment and tests continue running after a short interruption.

A better solution would be to boot a clean Windows instance for every test but we're not there yet. Until next time.

Here's another short and interesting story about problems we have to deal at Browserling. This story is about getting rid of annoying pop-up dialogs in browsers, such as alerts, error dialogs and add-on update dialogs.

So this one time when we were building Testling we started getting a nasty modal dialog in Chrome that paralyzed the browser and the tests wouldn't run. It said:

Your profile can not be used because it is from a newer version of
Google Chrome.

Some features may be unavailable. Please specify a different profile
directory or use a newer version of Chrome.

Here's how that dialog looked in Chrome:


Your profile can not be used because it is from a newer version of Google Chrome.

We were isolating each browser already through Sandboxie so changing the profile directory wasn't really a solution. I decided to write a quick hack that would simply click the OK button on this dialog.

I used Spy++ to find the window class of the dialog:


Spy++ in action.

And then I wrote a Win32 C++ program that detects if this dialog is present, and if it is, it clicks the OK button to get rid of it:

#include <windows.h>
#include <cstdio>

int WINAPI
WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    while (1) {
        HWND dialog = FindWindow("#32770", "Google Chrome");
        if (dialog) {
            printf("Found dialog: %x\n", dialog);
            HWND dialogItem = NULL;
            while (1) {
                dialogItem = FindWindowEx(dialog, dialogItem, NULL, NULL);
                if (dialogItem == NULL) {
                    break;
                }
                char windowText[255];
                GetWindowText(dialogItem, windowText, 255);
                if (strcmp(windowText, "OK") == 0) {
                    SetActiveWindow(dialog);
                    SendMessage(dialogItem, BM_CLICK, NULL, NULL);
                    break;
                }
            }
        }
        Sleep(1000);
    }
}

I pushed this program to github and called it chrome-dialog-killer.

Here's another similar problem that we faced in Browserling. We run many different FireFox versions on the same box and often FireFox wouldn't start cleanly. Instead it would complain about incompatible add-ons:

The following add-ons are not compatible with this version of
Firefox and have been disabled.
...
Firefox can check if there are compatible versions of these
add-ons available.

The incompatible add-ons dialog looked like this:


Incompatible add-ons FireFox dialog.

I tried disabling this add-on in all the FireFox version (Firefox 3 to Firefox 25) but we'd still get this alert sometimes. The browser wouldn't start and users had to click the "Don't Check" button. So, again, I used Spy++, found the dialog's windows class and wrote an even simpler program that simply sends the WM_CLOSE message to the dialog that closes it:

#include <windows.h>
#include <cstdio>

int WINAPI
WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    while (1) {
        HWND dialog = FindWindow("MozillaDialogClass", "FireFox Update");
        if (dialog) {
            printf("Found dialog: %x\n", dialog);
            HWND dialogItem = NULL;
            SendMessage(dialog, WM_CLOSE, 0, 0);
        }
        Sleep(2000);
    }
}

I also pushed this program to github and called it firefox-update-dialog-killer.

Similarly we can get rid of alert() dialogs in Testling as they're unnecessary and halt the JavaScript execution.

Modern GUIs and interfaces should never use modal dialogs as they provide really unpleasant user experience and make automating things difficult. Until next time.

I thought I'd write this short article about how we fixed a nasty bug at Browserling together with my friend James Halliday yesterday.

Long story short we were testing Browserling in the latest FireFox and we got this nasty exception that said:

uncaught exception: [object Object]

Here's how it looked in Firebug:


uncaught exception: [object Object]

FireBug didn't show the line number where it was thrown from and we couldn't find a way how to make it show the stack trace. We tried stepping through the code and setting breakpoints at some potential locations but didn't get us anywhere.

We were stuck and annoyed.

So we came up with a very hacky Perl one-liner that appends a console.log to almost every function definition:

perl -i -pe 's/function.*{$/$&."\n console.log($.);"/e' bundle.js

What this one-liner does is it finds all lines that have string function in them and that end with { and appends a console.log with the current line number to the beginning of the function.

For example, this code piece:

function foo (x) { 
   return 50/x;
}

Gets rewritten as:

function foo (x) { 
console.log(1);
   return 50/x;
}

Our thinking was that we should get the line number of the last function call before the exception was thrown or some function call nearby.

And it worked!

We refreshed Browserling and we got an awesome trace with lots of line numbers followed by the same uncaught exception error:

...
11248
11157
11257
11147
uncaught exception: [object Object]

Here's how it looked in FireBug:


lots of console.log's with line numbers followed by uncaught exception error

Next we checked the line 11147 in the original file (line 11914 in the updated file because the one-liner offsets line numbers) and we found the exception that we were looking for:

error = function (m) {                                                                                                 
    // Call error when something is wrong.
    throw {
        name:    'SyntaxError',
        message: m,
        at:      at,
        text:    text
    };
},

A fix quickly followed and we got Browserling working in the latest FireFox! Until next time.