Workaround for crashing Electron/Atom applications!

A few days ago  all my Electron (Atom Shell) apps started crashing on my Ubuntu 17.10  (Artful Aardvark) machine: Skype, Discord, Slack…  and each stack trace looks very much like this:

#0 0x0000000003419062 in ()
#1 0x0000000003f96086 in __start_google_malloc ()
#2 0x00000000034b9dc5 in calloc ()
#3 0x00007ffff20dc5d1 in g_malloc0 () at /lib/x86_64-linux-gnu/libglib-2.0.so.0
#4 0x00007ffff4afc4c9 in () at /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#5 0x00007ffff4b01855 in g_type_register_static () at /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#6 0x00007ffff4b01af5 in g_type_register_static_simple () at /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0
#7 0x00007ffff5c93f24 in gdk_display_manager_get_type () at /usr/lib/x86_64-linux-gnu/libgdk-x11-2.0.so.0
#8 0x00007ffff5c93f69 in gdk_display_manager_get () at /usr/lib/x86_64-linux-gnu/libgdk-x11-2.0.so.0
#9 0x00007ffff6070954 in () at /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0
#10 0x00007ffff6056f28 in () at /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0
#11 0x00007ffff20e2fdf in g_option_context_parse () at /lib/x86_64-linux-gnu/libglib-2.0.so.0
#12 0x00007ffff6057538 in gtk_parse_args () at /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0
#13 0x00007ffff60575b9 in gtk_init () at /usr/lib/x86_64-linux-gnu/libgtk-x11-2.0.so.0
#14 0x0000000001049626 in ()
#15 0x000000000104f1e7 in ()
#16 0x0000000001051656 in ()
#17 0x0000000003f6897b in brightray::BrowserMainParts::PreEarlyInitialization() ()
#18 0x0000000003e01169 in atom::AtomBrowserMainParts::PreEarlyInitialization() ()
#19 0x00000000015f6cf4 in ()

I don’t really know what’s on foot here, but Google led me to the GTK2_RC_FILES environment variable.

If I set this to empty, all these applications start properly!

Example starting Skype, note the space after the equals sign:

$ GTK2_RC_FILES= skypeforlinux

or

$ export GTK2_RC_FILES=
$ skypeforlinux

Can someone explain this error and what a proper fix would look like?

Update: Setting the XDG_CONFIG_DIRS environment variable to empty also works as a workaround!

Lova – Java 8 functional interface for AsyncTask on Android

I call the class Lova – in Swedish “to promise something” is “att lova något” .

This assumes you have converted your Android project to compile with Jack.

Warning: Lambdas do not currently work with multidex! See issue 226867.

This implementation only supports a single input parameter to the background task, but it the doInBackground method could easily be changed to send the full array instead.

If you need to report progress or handle cancellation of the AsyncTask, this implementation is too simple.

 

 

Limitations of Apple iOS captive portal web browser

At my employer Softhouse  (the best IT consultancy in Karlskrona, and we’re hiring!) I recently got the requirement to make an AngularJS web application work properly in the captive portal window on Apple iOS.

These requests are made with HTTP header:

User-Agent: CaptiveNetworkSupport-325.10.1 wispr

A captive portal is the login screen you get when you connect to many wifi access points at hotels, airports, and similar. The application works fine in a normal Safari browser on iOS, but not in the captive portal web browser.

The captive portal web browser is almost a complete web browser, but while normal Safari session on iOS can be debugged over USB, it is not possible to debug the captive portal web browser! (If you figure it out, please comment below!)

When I could not access the JavaScript console, I had to resort to debug by displaying application state on the web page.

Finally I discovered that the JavaScript application stopped working after calling Windows.sessionStorage.setItem().

Yes, for reasons hidden in the annals of history the AngularJS application depends on Windows.sessionStorage. The original developers probably had a good reason. Or at least some reason.

The session storage service in the application looked something like this:

return {
   get: function(key) {
      return sessionStorage.getItem(key);
   },
   set: function(key, val) {
      sessionStorage.setItem(key, val);
   },
   unset: function(key) {
      sessionStorage.removeItem(key);
   }
};

So maybe sessionStorage is not defined? I tried a simple:

if (sessionStorage) {
    return {
        get: function (key) {
            return sessionStorage.getItem(key);
        },
        set: function (key, val) {
            sessionStorage.setItem(key, val);
        },
        unset: function (key) {
            sessionStorage.removeItem(key);
        }
    };
} else {
    var session = {};
    return {
        get: function (key) {
            return session[key];
        },
        set: function (key, val) {
            session[key] = String(val);
        },
        unset: function (key) {
            delete session[key];
        }
    };
}

But, same error!

According to Apple’s own documentation on Key-Value Storage, Safari can throw an exception from sessionStorage.setItem() and a Stack Overflow comment states:

I found the same behaviour on Safari to be caused by private mode browsing. It seems that while on private browsing Safari does not allow local storage to be used at all.

Maybe the captive portal works like the private mode  browsing…?

So, let’s try this code:

var hasSessionStorage = !!sessionStorage;

if (hasSessionStorage) {
    try {
        sessionStorage.setItem("hasSessionStorage", true);
    }
    catch (e) {
        hasSessionStorage = false;
    }
}

if (hasSessionStorage) {
    return {
        get: function (key) {
            return sessionStorage.getItem(key);
        },
        set: function (key, val) {
            sessionStorage.setItem(key, val);
        },
        unset: function (key) {
            sessionStorage.removeItem(key);
        }
    };
} else {
    var session = {};
    return {
        get: function (key) {
            return session[key];
        },
        set: function (key, val) {
            session[key] = String(val);
        },
        unset: function (key) {
            delete session[key];
        }
    };
}

Finally, it works!

Freemium

I’m currently designing a smart phone game that I plan to monetize through a freemium model and came across the article Freemium Games Get The South Park Treatment by Felix Dicit.

He references a South Park episode where they crack down on Freemium games: US linkSwedish link.

My takeaway from this is that I need to be careful in how I implement the freemium model in the game. I don’t want to end up in a South Park episode. Or maybe I do?

ng-transclude that also transcludes scope

With the built-in ng-transclude the the scopes become siblings. What if we want the transcluded HTML to inherit the scope of our directive?

Thanks to Controlling Scope on the Transclude Function on ng-nuggets I was able to figure this out:

    angular
        .module('myApp.myModule')
        .directive('myDirective', myDirective);

    function myDirective() {
        return {
            controller: Controller,
            transclude: true,
            restrict: 'E',
            controllerAs: 'vm',
            link: linkThatTranscludeWithOurScope,
            scope: {}
        };
    }

    function linkThatTranscludeWithOurScope(scope, element, attrs, ctrl, transclude) {
        transclude(scope, function (clone) {
            element.append(clone);
        });
    }

PS. Do not include any template with this directive!

Increase disk size for OpenShift Origin Virtual Machine

Loving OpenShift, but having more than the three projects that already cost more than I earn from them I run an OpenShift Origin Virtual Machine on my home server.

So today I was trying to get Uptime running on OpenShift via uptime-openshift. A truly wonderful way of installing applications, except that it didn’t go so well:

$ rhc app create uptime nodejs-0.10 mongodb-2.4 --from-code=//github.com/rkmallik/uptime-openshift
Application Options
-------------------
Domain: origin
Cartridges: nodejs-0.10, mongodb-2.4
Source Code: //github.com/rkmallik/uptime-openshift
Gear Size: default
Scaling: no

Creating application 'uptime' ... 
The server did not respond correctly. This may be an issue with the server configuration or with your connection to the server (such as a Web proxy or firewall). Please
verify that you can access the OpenShift server //172.16.3.3/broker/rest/domain/origin/applications

Or…

$ rhc app create uptime nodejs-0.10 mongodb-2.4 --from-code=//github.com/rkmallik/uptime-openshift
Application Options
-------------------
Domain: origin
Cartridges: nodejs-0.10, mongodb-2.4
Source Code: //github.com/rkmallik/uptime-openshift
Gear Size: default
Scaling: no

Creating application 'uptime' ... Unpacking premade journal
tar: journal/prealloc.1: Wrote only 2048 of 10240 bytes
tar: Exiting with failure status due to previous errors

What’s going on? It turns out I was running low on disk space. The virtual machine image was only 8 GB and there was too little disk space left when the Mongo cartridge wanted to install the pre-allocated journals!

So, time to enlarge the disk! In short, the steps I took were:

  1. Convert virtual machine disk image to .vdi format
  2. Enlarge .vdi disk image
  3. Add partition with new disk space
  4. Add new partition to LVM volume group
  5. Extend LVM logical volume
  6. Resize file system

Now, let’s dive into the details!

Convert virtual machine disk image to .vdi format

Shutdown the virtual machine first!

As the VirtualBox user on the hypervisor, in the directory for the virtual machine:

$ VBoxManage clonehd origin-vm.vmdk origin-vm.vdi --format VDI
0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
Clone hard disk created in format 'VDI'. UUID: 646d9ed4-c751-45a3-9f08-0946e11591c9

Enlarge .vdi disk image

As the VirtualBox user on the hypervisor, in the directory for the virtual machine:

$ VBoxManage modifyhd origin-vm.vdi --resize 81920
0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%

Enlarge it with as much as you want to allow the disk image to grow on the hypervisor! The unit is megabytes.

Now detach the .vmdk file and attach the .vdi file from the virtual machine. I did this with phpVirtualBox, so the corresponding command line is left as an exercise for the reader.

Delete the the .vmdk file, or keep it as backup if you like.

Add partition with new disk space

Start the virtual machine and login. Default root password is changeme. Being a Linux user for about 15 years, I’m no stranger to fdisk:

# fdisk /dev/sda

WARNING: DOS-compatible mode is deprecated. It's strongly recommended to
 switch off the mode (command 'c') and change display units to
 sectors (command 'u').

Command (m for help): c
DOS Compatibility flag is not set

Command (m for help): u
Changing display/entry units to sector

Command (m for help): n
Command action
 e extended
 p primary partition (1-4)
p
Partition number (1-4): 3
First sector (16777216-167772159, default 16777216): 
Using default value 16777216
Last sector, +sectors or +size{K,M,G} (16777216-167772159, default 167772159): 
Using default value 167772159

Command (m for help): t
Partition number (1-4): 3
Hex code (type L to list codes): 8e
Changed system type of partition 3 to 8e (Linux LVM)

Command (m for help): p

Disk /dev/sda: 85.9 GB, 85899345920 bytes
255 heads, 63 sectors/track, 10443 cylinders, total 167772160 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x0003c6cc

 Device Boot Start End Blocks Id System
/dev/sda1 * 2048 1026047 512000 83 Linux
/dev/sda2 1026048 16777215 7875584 8e Linux LVM
/dev/sda3 16777216 167772159 75497472 8e Linux LVM

Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.

WARNING: Re-reading the partition table failed with error 16: Device or resource busy.
The kernel still uses the old table. The new table will be used at
the next reboot or after you run partprobe(8) or kpartx(8)
Syncing disks.

If told to reboot, do that. Otherwise Linux will not show the new partition.

Add new partition to LVM volume group

# vgextend vg_broker /dev/sda3
 No physical volume label read from /dev/sda3
 Physical volume /dev/sda3 not found
 Physical volume "/dev/sda3" successfully created
 Volume group "vg_broker" successfully extended

Extend LVM logical volume

Use all available space:

# lvextend -l +100%FREE /dev/mapper/vg_broker-lv_root
 Extending logical volume lv_root to 78,71 GiB
 Logical volume lv_root successfully resized

Resize file system

First find out the LSize in sectors:

# lvs --units s
 LV VG Attr LSize Pool Origin Data% Move Log Cpy%Sync Convert
 lv_root vg_broker -wi-ao---- 165060608S 
 lv_swap vg_broker -wi-ao---- 1671168S

Second, resize the file system. Change capital S to lower-case:

# resize2fs /dev/mapper/vg_broker-lv_root 165060608s
resize2fs 1.41.12 (17-May-2010)
Filesystem at /dev/mapper/vg_broker-lv_root is mounted on /; on-line resizing required
old desc_blocks = 1, new_desc_blocks = 5
Performing an on-line resize of /dev/mapper/vg_broker-lv_root to 20632576 (4k) blocks.
The filesystem on /dev/mapper/vg_broker-lv_root is now 20632576 blocks long.

 Done!

If only I remembered why I needed more disk space?!

Why use I²C to access 1-Wire from Raspberry Pi?

A friend of mine asked the excellent question on why I bought an I²C 1-Wire expansion module for 300 SEK (about €30) when there are kernel drivers for using 1-Wire over GPIO right away and exposing the 1-Wire network below /sys/bus/w1/. I honestly didn’t know of this option!

Now I’ve made some investigations and realized that for example the DS2406 1-Wire chips I already bought are not yet supported by the kernel. There is a patch, for those who like to compile their own Raspberry Pi kernel. I don’t.

Also, OWFS seems to do an OK job of hiding the way of interfacing the 1-Wire network, so as long as use OWFS to access my 1-Wire stuff I should be able to switch to the w1 kernel drivers in the future.

For now, I will continue to use the I²C 1-Wire expansion module, because it works fine, I already bought more than one of them (!), and all my stuff is supported.

Home automation with 1-Wire and Raspberry Pi

Me and my wife recently bought a cottage half an hour’s drive from where we live.

She is enjoying herself immensely with interior decorating, grinding floors and mowing the lawn. She is also looking forward to washing and painting the windows and exterior walls…

Naturally I will also do some work on and around the cottage. I use to say that I’m only handy when forced to, but that’s not entirely true… 🙂

Now for the fun part. I have taken on to implement home automation for the cottage. At start it will be mostly monitoring temperature, measuring electricity consumption and checking door and motion sensors.

The heart of the home automation is a Raspberry Pi running Rasbian. On the Raspberry Pi I have mounted an I²C 1-Wire expansion module and installed owfs.

My main sources of 1-Wire hardware is the special interest Swedish web shop m.nu. For other stuff I use the Radio Shack of Sweden: Kjell & Company, and, of course, eBay!

This is a list of some stuff I bought on eBay for various parts of this project. Prices provided in case want to compare to ordinary web shops… 🙂

  • 10 × PIR motion sensors, $12.59
  • RJ45/RJ11 cable tester, $2.91
  • 100 × RJ11 plugs, C $4.33
  • RJ45/RJ11 Crimp Tool, GBP 4.99
  • NoIR camera module for Raspberry Pi, $28.49
  • 2 × Infrared lights for NoIR camera module, $9.49
  • 9800mAh DC 12V rechargeable Lithium-ion Battery, $27.53
  • Micro USB splitter charge cable, GBP 1.49
  • 20 × magnetic door/window sensors, $17.12

So, what is all that stuff good for? My plan is to make a series of posts about the various parts of the project, but I make no guarantees… 🙂