Windows Subsystem for Linux


I never paid too much attention to the Windows Subsystem for Linux (WSL). But recently I wanted to do some gbd debugging. So I started with Ubuntu in Virtual Box. This was a little bit slow on my Laptop so I searched for a better solution. What is easier than installing Ubuntu from the Windows Microsoft Store? With this app I got full Linux command line support. But how does this work?

The ability to support different subsystems was built into the Windows kernel long time ago. The first Windows NT version did support OS/2 console application for instance. Windows 10 can now run native Linux ELF64 binaries. It does this without emulation and without recompiling Linux code.

The WSL consists of user mode and kernel mode components. In kernel mode there is a driver which translates Linux system calls to the Windows kernel. Sometimes there is a direct mapping, sometimes there is some extra work to do.

In user mode there is the pico process in which system calls are dispatched to this driver. This process is an outcome of the Drawbridge research prototype. A goal of this prototype was to decouple a Windows process from the underlying OS on which it is executed. This is tailor-made for running Linux applications on Windows 10. Although it was not designed for this.

To use WSL you need to active the Windows Feature “Windows-Subsystem for Linux”. This installs the basic functionality. When this is done you can install a distribution from the Microsoft Store.

When I started Ubuntu the first time I saw the error message “Unsupported console settings. In order to use this feature the legacy console must be disabled.“ constantly filling up the console window. The problem was that the legacy console was activated which is obviously incompatible to WSL.

Advertisements

RavenDB, Docker and F#


Here is a little F# application which connects to a RaveDB database, adds an entry and reads them. I used this application to play with RavenDB running inside a Docker container.

open Raven.Client.Documents

type Customer = {
    FirstName: string
    LastName: string
}

[<EntryPoint>]
let main argv =
    printfn "Hello RaveDB!"

    use store = new DocumentStore ()
    store.Urls <-  [|"http://10.0.75.1:8080"|]
    store.Database <- "RavenDB1"
    use store = store.Initialize ()
    
    use session = store.OpenSession ()
    let customer1 = { FirstName = "Guy"; LastName = "Montag" }
    session.Store customer1
    session.SaveChanges ()

    let customers = query {
        for customer in session.Query<Customer>() do
        select customer
    }

    customers |> Seq.iter (printf "%A")

    printfn "Done!"
    0

You can download the full project from my GitHub repository.

https://github.com/chuchu/sandbox/tree/master/ravendb/raven1

From the code you can see that the database runs on 10.0.75.1 which is the IP address of my Docker bridge.

To execute a RavenDB Docker container you need to download the image first. You can do this by executing the command:

docker pull ravendb/ravendb

This will download the latest ubuntu based version. To run the image its best to use the run-ubuntu1604.ps1 powershell script which is provided by the RavenDB project.

ubuntu1604.ps1 -AuthenticationDisabled -PublicServerUrl "http://10.0.75.1:8080"

Disabling authentication is good for testing purposes. So there is no need to deal with certificates. Why it is necessary to provide the PublicServerUrl is something what I don’t really understand completely. But this article explains it a little bit.

https://ayende.com/blog/178819/bug-stories-how-do-i-call-myself

Now you can open your browser, go to http://10.0.75.1:8080 and create the database RavenDB1. When the database is up and running the application can be executed.

dotnet run

When everything works as expected the F# application can be deployed in a container too. Before the image can be created you need to make a release build.

dotnet publish -c release -o app

The docker file is available in the repository. So you just need to type

docker build -t hello-ravendb .

Have a look for the line

Successfully built 388344c214f3

Your ID is surely different, but you need it to run your image.

docker run 388344c214f3

You should see the same output as when the application was executed directly.

Falscher Debugger


Mit unter soll es vorkommen, dass sich in einer Anwendung ein Fehler eingeschlichen hat. Zumindest in denen, die man nicht selbst Programmiert hat. Stößt das Framework auf einen solchen Fehler erscheint, sofern das SDK installiert ist und Debug Symbols vorhanden sind, ein Fenster, in welchem man einen Debugger starten kann. Bei mir war nun das Problem das ich bei einer .NET 2.0 Anwendung nur die Debugger für das 1.1er Framework wählen konnte, die dann mit dem Prozess natürlich ganz und gar nicht zurecht kamen. Die Lösung des Problems lag in der Registry. Dort fand ich unter [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework] folgende zwei Schlüssel:

"DbgManagedDebugger"="\"C:\Programme\Gemeinsame Dateien\Microsoft Shared\VS7Debug\vs7jit.exe\" PID %d APPDOM %d EXTEXT \"%s\" EVTHDL %d"

"DbgJITDebugLaunchSetting"=dword:00000002

Wie man sieht, ist dort der Debugger von VS 7, sprich .NET 1.1, angegeben. Also kann das ja nicht gehen. Ändert man die Wete der beiden Schlüssel auf:

"DbgManagedDebugger"="\"C:\WINDOWS\system32\vsjitdebugger.exe\" PID %d APPDOM %d EXTEXT \"%s\" EVTHDL %d""DbgJITDebugLaunchSetting"=dword:00000010

sieht das Ganze schon besser aus. Offenbar lag der Fehler daran, dass ich VS 2005 vor der 2003er Version installiert habe. Wie auch immer. Jetzt funktioniert es wieder super. Wichtig war mir das Ganze um einen selbst geschriebenen Windows Service zu Debuggen. Das geht ja von Haus aus ziemlich schlecht. Schreibt man aber System.Diagnostics.Debugger.Launch(); wird in dieser Zeile der Debugger gestartet. Das kann sehr hilfreich sein.