Outputting QR codes on the terminal

In these dark ages, a lot of software (mostly chat apps) only work on smartphones. While it’s easy to connect a USB-OTG hub to most smartphones (even my dirt-cheap Android smartphone supports this (now three years old)), having two keyboards on your desk can be kind of annoying.

While there are a bunch of possible solutions to this problem, many of these solutions do not fix the problem when you’re not on your home setup. Which is why I often just use QR codes to send URLs to my phone, and there are a lot of QR code generator sites out there.

QR code generator sites are useful because they work everywhere, but many are slow and clunky. Perhaps acceptable in a pinch, but… what if you could just generate QR codes on the terminal?

Well, some cursory googling revealed this library: https://github.com/qpliu/qrencode-go, which doesn’t have any external (non-standard library) dependencies, is short enough to skim over for malicious code, and comes with an easily adapted example. (I am reasonably confident that there is no malicious code at ad8353b4581fa11fc01a50ebf56db3833462fc13.)

Note: I very rarely use Go. Here is what I did to compile this:

$ git clone https://github.com/qpliu/qrencode-go
$ mkdir src
$ mv qrencode/ src/

$ cat > qrcodegenerator.go
package main
import (
func main() {
var buf bytes.Buffer
for i, arg := range os.Args {
if i > 1 {
if err := buf.WriteByte(' '); err != nil {
if i > 0 {
if _, err := buf.WriteString(arg); err != nil {
grid, err := qrencode.Encode(buf.String(), qrencode.ECLevelQ)
if err != nil {
$ GOPATH=$PWD go build qrcodegenerator.go
$ ./qrcodegenerator test

Note: the above code is adapted from example code in the README.md file and is therefore LGPL3.

Since Go binaries are static (that’s what I’ve heard at least), you can then move the executable anywhere you like (e.g. ~/bin) and generate QR codes anywhere. Note that they’re pretty huge, i.e. for ‘https://blog.qiqitori.com’ (26 bytes) the QR code’s width will be 62 characters. For e.g. ‘https://blog.qiqitori.com/2020/10/outputting-qr-codes-on-the-terminal/’ (this post) the width is 86 characters.

Standing on the shoulder of giants

Making new discoveries usually requires knowledge from previous discoveries. Discoveries are published as text in research papers. Scientists find these research papers using keywords they plug into a search engine or when other research papers cite them. Being able to search by keywords has obviously made scientific research much easier than before.

However, the research papers themselves are still written in natural languages, and unless the authors avoid using grammatical features like the words “it” or “them” to avoid repeating nouns over and over again, it’s difficult to extract meaning from them.

So perhaps people shouldn’t be writing research papers in (e.g.) English and instead use something that is easier for computers to parse. The research paper would contain claims, some numeric indicator for how certain these claims are (or from where they came), how these claims came about (e.g. experiment (with instructions for how and experiment was set up and why), logical reasoning (with the actual chain of reasoning), etc.). Then you could, for example, search for claims, instead of just keywords.

Instead of just using the keywords “ocean plastic waste”, you could search for “plastic waste in oceans negatively impacts ocean fauna”. Instead of typing in this query, you would choose every noun, verb and other qualifiers from a searchable menu. You would be able to display this menu in any language. The words in the menu would all mean a specific thing, and anybody would be able to look at the definitions and properties of every word. Eventually, the system could be programmed to (e.g.) look at two different claims and judge whether these claims might be related, based on common subjects or objects, and generate potential new claims all by itself. For example, claim 1: “Thunderstorms may under certain circumstances cause blackouts” and claim 2: “Certain atmospheric conditions cause thunderstorms” would logically mean that “certain atmospheric conditions cause blackouts”, which is true. The system probably shouldn’t let users use the word “certain” though.

How hard would it be to make such a system? Well, it’s best to start in a single niche and slowly expand the system. Here’s a very simple (completely static) example that is a bit different in that it just generates natural English or Japanese text based on what values are selected in the menus: https://blog.qiqitori.com/cve_generator/

Saving the selections would be a first step in the right direction. Currently, only one “allows attackers to:” is allowed, but you would probably want to 1) allow an arbitrary-length chain 2) something indicating the author’s degree of certainty (“may allow”), 3) add other verbs, other nouns, and 4) the reasoning behind a set of these claims (it gets complex here, but in the end you just have to select subjects, verbs, and objects, ifs, etc.).

Perhaps selecting things from a menu would get old quick (unless you just do it for the main claims). So the computer could try its best to analyze a sentence and ask the user to confirm that its interpretation is correct. The preceding sentence could be analyzed like this, but you’ll see that this could be tricky and just selecting something from a menu might be the better option after all: So [potential solution for previous follows:] the computer [the software] could try its best [could potentially (but probably wouldn’t manage to do this perfectly)] to analyze a sentence [analyze a given input sentence] and [afterwards] ask the user to [force the user] confirm that its [the software’s] interpretation [of the given input sentence] is correct [confirm … or force the user to edit the interpretation using a menu]. As you can see, there is a lot of context involved, which makes it hard to derive (e.g.) claims from natural text.

As you can see in the CVE generator, having the facts makes it somewhat easy for the system to generate text in any language for humans to read and think about

KDE: Windows freeze or flicker but application doesn’t crash

I’m running KDE on two different systems, and one of them exhibits the following problem very often, and the other just did for the first time:

Windows stop updating their content, and perhaps flicker a bit. Switching to a different window and back causes the window contents to be updated, but still frozen. Which means that the application itself is not crashed.

The following command fixes this:

kwin --replace

You can run this from the run command prompt (Alt+F2) (also called Plasma search or krunner), or you could run it in a terminal. (You’d have to make sure the process doesn’t exit when you close the terminal though.)

If everything appears to be frozen and you can’t get to the run command prompt, you could still switch to a console, log in, and try running the following:

DISPLAY=:0 kwin --replace

Both systems have internal Intel graphics (quite different chipsets though) and KDE5.

The above commands will fix the problem for that time. Your open applications should not be affected by the change. I haven’t looked much into permanent fixes, but changing the rendering backend (System Settings → Display and Monitor → Compositor) may change the frequency the problem is triggered or maybe even get rid of it altogether. (I felt that OpenGL 2.0 probably triggered the problem fewer times than OpenGL 3.1.)

I’ve noticed a fair amount of traffic to my KDE-related posts. If you run into any weird KDE problems that you don’t know how to fix, feel free to leave a comment and ask.

Meltdown / Spectre Kernel Patch Benchmarks on Older Systems

The Meltdown patch for the Linux kernel makes use of the relatively new PCID instruction. I still sometimes use my old laptop, which contains a Core 2 Duo Penryn CPU (T7250), and does not support the PCID instruction, so I did a quick UnixBench run to see what kind of difference the absence of the PCID instruction would make. At the end of this article, I have a bonus “benchmark” for an alternative way to mitigate Meltdown: disabling the CPU’s caches. All my tests were performed on Debian Wheezy (currently oldstable) using kernel version 3.16.0-5-amd64.

First of all, here are another person’s results for a CPU that supports PCID. And since that’s in Japanese, here’s the important bit:

Test Before After Change (positive is better)
System Call Overhead 5391.9 4009.7 -25.63%

Now, my tests on the Penryn CPU:

Test Before After Change (positive is better)
Dhrystone 2 using register variables 3360.4 3414.1 +1.60%
Double-Precision Whetstone 724.1 724 -0.01%
Execl Throughput 1351.7 1222.9 -9.53%
File Copy 1024 bufsize 2000 maxblocks 1582 1244 -21.37%
File Copy 256 bufsize 500 maxblocks 1255.9 922.1 -26.58%
File Copy 4096 bufsize 8000 maxblocks 1982.4 1810.6 -8.67%
Pipe Throughput 1672.8 765.4 -54.24%
Pipe-based Context Switching 1108.3 671 -39.46%
Process Creation 1150 1025.3 -10.84%
Shell Scripts (1 concurrent) 1995.7 1909 -4.34%
Shell Scripts (8 concurrent) 1831.8 1743.3 -4.83%
System Call Overhead 1705.6 544.9 -68.05%
System Benchmarks Index Score 1535.8 1160.9 -24.41%

And the raw data in case you are interested:

Before updating:

Test Score Unit Time Iters. Baseline Index
Dhrystone 2 using register variables 39215974.0 lps 10.0 s 7 116700.0 3360.4
Double-Precision Whetstone 3982.6 MWIPS 9.9 s 7 55.0 724.1
Execl Throughput 5812.4 lps 29.2 s 2 43.0 1351.7
File Copy 1024 bufsize 2000 maxblocks 626453.0 KBps 30.0 s 2 3960.0 1582.0
File Copy 256 bufsize 500 maxblocks 207854.8 KBps 30.0 s 2 1655.0 1255.9
File Copy 4096 bufsize 8000 maxblocks 1149781.6 KBps 30.0 s 2 5800.0 1982.4
Pipe Throughput 2080979.1 lps 10.0 s 7 12440.0 1672.8
Pipe-based Context Switching 443337.7 lps 10.0 s 7 4000.0 1108.3
Process Creation 14490.3 lps 30.0 s 2 126.0 1150.0
Shell Scripts (1 concurrent) 8461.7 lpm 60.0 s 2 42.4 1995.7
Shell Scripts (8 concurrent) 1099.1 lpm 60.1 s 2 6.0 1831.8
System Call Overhead 2558469.9 lps 10.0 s 7 15000.0 1705.6
System Benchmarks Index Score: 1535.8

After updating:

Test Score Unit Time Iters. Baseline Index
Dhrystone 2 using register variables 39842314.8 lps 10.0 s 7 116700.0 3414.1
Double-Precision Whetstone 3982.0 MWIPS 9.8 s 7 55.0 724.0
Execl Throughput 5258.5 lps 30.0 s 2 43.0 1222.9
File Copy 1024 bufsize 2000 maxblocks 492638.1 KBps 30.0 s 2 3960.0 1244.0
File Copy 256 bufsize 500 maxblocks 152610.9 KBps 30.0 s 2 1655.0 922.1
File Copy 4096 bufsize 8000 maxblocks 1050156.7 KBps 30.0 s 2 5800.0 1810.6
Pipe Throughput 952188.4 lps 10.0 s 7 12440.0 765.4
Pipe-based Context Switching 268401.0 lps 10.0 s 7 4000.0 671.0
Process Creation 12918.3 lps 30.0 s 2 126.0 1025.3
Shell Scripts (1 concurrent) 8094.2 lpm 60.0 s 2 42.4 1909.0
Shell Scripts (8 concurrent) 1046.0 lpm 60.1 s 2 6.0 1743.3
System Call Overhead 817288.1 lps 10.0 s 7 15000.0 544.9
System Benchmarks Index Score: 1160.9

Now, Mitigating Meltdown by switching off CPU caches:

You wouldn’t even want to run UnixBench without CPU caches. Here’s a “simpler” benchmark that tells you why:

# time perl -e 'for (1..1000000) {}'

real 0m0.056s
user 0m0.052s
sys 0m0.000s
# insmod disable_cache.ko
# time perl -e 'for (1..1000000) {}' 

real 0m44.689s
user 0m40.044s
sys 0m0.520s
# rmmod disable_cache

Unless you enjoy working on a system that is some 800 times slower. (Don’t try to do this in a GUI setting.)

Nonetheless, here’s some code to disable the CPU caches. (Modified from https://www.linuxquestions.org/questions/linux-kernel-70/disabling-cpu-caches-936077/)

#include <linux/init.h>
#include <linux/module.h>
#include <linux/smp.h>


void _disable_cache(void *p) {
 printk(KERN_ALERT "Disabling L1 and L2 caches on processor %d.\n", smp_processor_id());
 __asm__(".intel_syntax noprefix\n\t"
 "mov rax,cr0\n\t"
 "or rax,(1 << 30)\n\t"
 "mov cr0,rax\n\t"
 ".att_syntax noprefix\n\t"
 : : : "rax" );
void _enable_cache(void *p) {
 printk(KERN_ALERT "Enabling L1 and L2 caches on processor %d.\n", smp_processor_id());
 __asm__(".intel_syntax noprefix\n\t"
 "mov rax,cr0\n\t"
 "and rax,~(1 << 30)\n\t"
 "mov cr0,rax\n\t"
 ".att_syntax noprefix\n\t"
 : : : "rax" );

static int disable_cache_init(void)
 on_each_cpu(_disable_cache, NULL, 1);
 return 0;
static void disable_cache_exit(void)
 on_each_cpu(_enable_cache, NULL, 1);



obj-m += disable_cache.o

	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

Note that you need to indent using tabs in Makefile. CR0 can only be read from Ring 0, and thus a kernel module is needed.

Here’s some example code to just read the CR0 registers on all CPUs:

#include <linux/init.h>
#include <linux/module.h>
#include <linux/smp.h>


void cache_status(void *p) {
 long int cr0_30 = 0;
 __asm__(".intel_syntax noprefix\n\t"
 "mov %0, cr0\n\t"
 "and %0, (1 << 30)\n\t"
 "shr %0, 30\n\t"
 ".att_syntax noprefix\n\t"
 : "=r" (cr0_30));
 printk(KERN_INFO "Processor %d: %ld\n", smp_processor_id(), cr0_30&(1<<30)>>30);

static int cache_status_init(void) {
 on_each_cpu(cache_status, NULL, 1);
 return 0;
static void cache_status_exit(void) {
 on_each_cpu(cache_status, NULL, 1);


And the corresponding Makefile:

obj-m += cache_status.o

	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules


KDE: The Window Switcher installation is broken, resources are missing.

So I was highly displeased with the standard Breeze task switcher, and thought I’d get a few new ones by clicking the star icon next to the drop-down menu where you select the task switcher. My recommendation is “Grid”. Trying to use Grid, all I get is this error message:

The Window Switcher installation is broken, resources are missing.
Contact your distribution about this.

Hrm. So then I Google and look at code, waste time trying silly things, just to postpone this problem for another weekend. Well, it’s the next weekend now, and just when I’m about to dive back into the code… I restart X (i.e. re-login), and when I try to bring the message up one more time… It doesn’t appear anymore, and Grid and all the others are working! I try installing one more, and sure enough, it didn’t work, but one more re-login and tada. So the answer to this problem might be: restart your KDE session.

It’s still a bug though. But unfortunately I’m no longer interested in looking into this bug now. :(