Odi's astoundingly incomplete notes

New Entries

Improve font rendering in Firefox

If fonts in Firefox look uglier than in Chrome then probably LCD Filtering is not enabled in fontconfig.

In Gentoo enable LCD filtering like so:
eselect fontconfig enable 11-lcdfilter-default.conf
eselect fontconfig list
And make sure the other LCD filtering options are disabled. In my setup I get good fonts with:
Available fontconfig .conf files (* is enabled):
  [1]   10-autohint.conf *
  [2]   10-hinting-full.conf
  [3]   10-hinting-medium.conf
  [4]   10-hinting-none.conf
  [5]   10-hinting-slight.conf
  [6]   10-no-sub-pixel.conf
  [7]   10-scale-bitmap-fonts.conf *
  [8]   10-sub-pixel-bgr.conf
  [9]   10-sub-pixel-rgb.conf
  [10]  10-sub-pixel-vbgr.conf
  [11]  10-sub-pixel-vrgb.conf
  [12]  10-unhinted.conf
  [13]  11-lcdfilter-default.conf
  [14]  11-lcdfilter-legacy.conf
  [15]  11-lcdfilter-light.conf
  [16]  20-unhint-small-dejavu-sans.conf
  [17]  20-unhint-small-dejavu-sans-mono.conf
  [18]  20-unhint-small-dejavu-serif.conf
  [19]  20-unhint-small-vera.conf *
  [20]  25-unhint-nonlatin.conf
  [21]  30-metric-aliases.conf *
  [22]  40-nonlatin.conf *
  [23]  45-generic.conf *
  [24]  45-latin.conf *
  [25]  49-sansserif.conf *
  [26]  50-user.conf *
  [27]  51-local.conf *
  [28]  57-dejavu-sans.conf
  [29]  57-dejavu-sans-mono.conf
  [30]  57-dejavu-serif.conf
  [31]  60-generic.conf *
  [32]  60-latin.conf *
  [33]  60-liberation.conf
  [34]  63-source-pro.conf
  [35]  65-fonts-persian.conf *
  [36]  65-khmer.conf
  [37]  65-nonlatin.conf *
  [38]  66-noto-mono.conf *
  [39]  66-noto-sans.conf *
  [40]  66-noto-serif.conf *
  [41]  69-unifont.conf *
  [42]  70-no-bitmaps.conf
  [43]  70-yes-bitmaps.conf
  [44]  75-yes-terminus.conf
  [45]  80-delicious.conf *
  [46]  90-synthetic.conf *

posted on 2022-04-07 14:14 UTC in Code | 0 comments | permalink

Stackoverflow can break your locking scheme

Simple Java locking code, looking innocent, right?
    private ReentrantLock lock = new ReentrantLock();
    private void doIt() {
        boolean locked = lock.tryLock();
        try {
        } finally {
            if (locked) lock.unlock();

Well, only until you realize that a call to unlock() causes 4 nested method calls. So unlock() requires a little bit of free stack. But what happens when stack is tight? Well... unlock() will simply fail with a StackOverflowError of course and your lock is leaked.

Here is a little demo:
public class StackOfl implements Runnable {
    public static void main(String[] args) {
        new StackOfl().run();

    public void run() {
        try {
        } catch (Throwable e) {
        System.out.println("still locked? "+ lock.isLocked());
    private void test() {

    private ReentrantLock lock = new ReentrantLock();
    private void overflowStack() {
        boolean locked = lock.tryLock();
        try {
            overflowStack(); // 1. StackOverflowError occurs here
        } finally {
            if (locked) lock.unlock(); // 2. StackOverflowError occurs within here
        // avoid tail recursion optimization in compiler
This code overflows the stack on purpose within the try/finally block. Java dutifully executes the finally block on the first StackOverflowError just to run into another StackOverflowError during unlock(), which is the one that propagates up.

The output is something like this:
	at java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(ReentrantLock.java:149)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer.release(AbstractQueuedSynchronizer.java:1261)
	at java.util.concurrent.locks.ReentrantLock.unlock(ReentrantLock.java:457)
	at StackOfl.overflowStack(StackOfl.java:39)
	at StackOfl.overflowStack(StackOfl.java:37)
	at StackOfl.overflowStack(StackOfl.java:37)
still locked? true
java.util.concurrent.locks.ReentrantLock@7852e922[Locked by thread main]
You can clearly see the lock is leaked.
posted on 2022-02-22 08:37 UTC in Code | 0 comments | permalink

Gentoo updates su binary

If your Gentoo spits out cron errors like this:
run-parts: /etc/cron.daily/man-db exited with return code 1
after updating to sys-apps/util-linux-2.37.3 then you should run pwck to check the consistency of /etc/passwd, /etc/shadow etc.
# pwck 
user 'adm': directory '/var/adm' does not exist
user 'lp': directory '/var/spool/lpd' does not exist
user 'news': directory '/usr/lib/news' does not exist
user 'uucp': directory '/var/spool/uucppublic' does not exist
no matching password file entry in /etc/shadow
add user 'man' in /etc/shadow? y
no matching password file entry in /etc/shadow
add user 'smmsp' in /etc/shadow? n
no matching password file entry in /etc/shadow
add user 'portage' in /etc/shadow? y
no matching password file entry in /etc/passwd
delete line 'games:*:9797:0:::::'? y
no matching password file entry in /etc/passwd
delete line 'guest:*:9797:0:::::'? y
pwck: the files have been updated
On all my machines the man and portage users were not in shadow. And you can userdel smmsp if you are not using qmail too.

The problem arises since the su binary from sys-apps/shadow has been replaced with the util-linux version (see su USE flag).

posted on 2022-01-28 10:22 UTC in Code | 1 comments | permalink
Thanks for spelling it out. Current latest stable sys-apps/man-db-2.9.4-r1 doesn't seem to be requiring new-enough sys-apps/util-linux-2.37.4, and man-db cron job starts failing every day.

Gentoo switches to libxcrypt

Update these packages before others:
emerge -v1 virtual/libcrypt sys-libs/libxcrypt
Otherwise you can run into dependency issues if there are a lot of other package updates. Also this gets you into a stable state again (as it causes a glibc rebuild) more quickly when you update a system that can't afford longer downtimes.
posted on 2021-12-02 15:40 UTC in Code | 0 comments | permalink

Cast CLOB to BLOB in Oracle

select TO_BLOB(UTL_RAW.CAST_TO_RAW(myclob)) from mytable
This will provide a CLOB column as a BLOB. The character set / encoding that is used here is to be determined. Probably DB default.
posted on 2021-11-19 13:15 UTC in Code | 0 comments | permalink

Gentoo switches to Python 3.9

To find remaining packages that still have a python3_8 useflag that prevents depcleaning 3.8:
 find /var/db/pkg -name USE | xargs grep python3_8

posted on 2021-11-09 11:05 UTC in Code | 0 comments | permalink

Gentoo has a binary Rust package

Rust takes a lot of time and resources to compile. Very annoying.

Fortunately there is a binary package: dev-lang/rust-bin
But virtual/rust prefers the source package via
RDEPEND="|| ( ~dev-lang/rust-${PV}[${MULTILIB_USEDEP}] ~dev-lang/rust-bin-${PV}[${MULTILIB_USEDEP}] )"
So any sane person should add dev-lang/rust to their /etc/portage/package.mask file, so portage picks rust-bin by default.

posted on 2021-06-22 16:53 UTC in Code | 0 comments | permalink

Root can NOT access all files

If you think that root has universal privilege on the filesystem, then you may need to update your opinion.

Consider an NFS share for example that is exported from the server as:

and the permissions on that directory are:
drwxrws---.  2 foo bar    6 Apr 15 17:33 nfs
On the client where that NFS share is mounted the directory looks innocuous (same as above). But when root tries to enter it
# cd /var/nfs
bash: cd: /var/nfs: Permission denied
What happens here? The NFS share uses root squashing, which will map the client's root user to the local anonymous user.
As the man page for exports explains:
Very often, it is not desirable that the root user on a client machine is also treated as root when accessing files on the NFS server. To this end, uid 0 is normally mapped to a different id: the so-called anonymous or nobody uid. This mode of operation (called 'root squashing') is the default, and can be turned off with no_root_squash.

So root being able to access almost everything is only true for "normal" filesystems, but a network filesystem or any other form of mount (fuse!) may behave differently althogether.
Beware of that fact when doing backups. Running backup as root may not be sufficient.

posted on 2021-04-16 08:39 UTC in Code | 0 comments | permalink

Gentoo switches to Python 3.8

With this change Gentoo replaces the current Python 3.7 with 3.8. Unfortunately this makes your next emerge session a bit more interesting.

emerge -uvD world may complain that it wants python 3.7 USE flags
# required by @world (argument)
>=dev-python/setuptools-50.3.0 python_targets_python3_7
and that there are conflicts
  (dev-python/pygobject-3.36.1-r1:3/3::gentoo, installed) USE="cairo -examples -test" ABI_X86="(64)" PYTHON_TARGETS="python3_7 -python3_6 -python3_8 -python3_9"
  pulled in by ...

  (dev-python/pygobject-3.36.1-r1:3/3::gentoo, ebuild scheduled for merge) USE="cairo -examples -test" ABI_X86="(64)" PYTHON_TARGETS="python3_8 -python3_6 -python3_7 -python3_9"
  pulled in by...
In that case first rebuild packages with new USE flags:
emerge -N1avD world

Or try changed USE flags only, which may give better results:
emerge -U1avD world

This will switch existing packages to use 3.8 instead of 3.7. After that tell the system that it should prefer 3.8:
eselect python set --python3 python3.8
Update: eselect-python is now gone. Directly edit /etc/python-exec/python-exec.conf

If the world update still complains about conflicts then there are installed packages that have no python 3.8 support. Uninstalling them and depclean may be an option, or ignoring the dependency.

To find remaining packages that still have a python3_7 useflag that prevents depcleaning 3.7:
find /var/db/pkg -name USE | xargs grep python3_7

posted on 2020-12-04 10:05 UTC in Code | 0 comments | permalink

Gentoo removes /lib32

For a long time Gentoo had this exotic layout (same for /usr/lib32):

lrwxrwxrwx   1 root root     5 Aug 31 09:59 lib -> lib64
drwxr-xr-x   2 root root  4096 Aug 31 09:59 lib32
drwxr-xr-x  15 root root 12288 Oct 15 18:06 lib64

This is now changing to what most other distros are doing:

drwxr-xr-x  14 root root       4096 Nov  9 11:45 lib
drwxr-xr-x  10 root root      12288 Nov 11 09:28 lib64

/lib32 becomes the new /lib and /lib64 hold only 64bit specific files. All generic files now go into /lib (and no longer /lib64). Nobody hard-wires /lib32 anymore.

The migration is pretty smooth with the app-portage/unsymlink-lib utility. On all my systems it was enough to do this:

emerge -1v app-portage/unsymlink-lib
unsymlink-lib --analyze
# check the output for orphaned files and clean up, run analyze again
unsymlink-lib --migrate
unsymlink-lib --finish
eselect profile set 1  (or whatever you chose)
emerge -1av gcc
emerge -1av libtool binutils
source /etc/profile
emerge -1av glibc sandbox
# check for remaining packages
emerge -1pvD /lib32 /usr/lib32 /usr/lib/llvm/*/lib32

I encountered only some small catches:

1. If you maintain a binhost (one that builds and serves binary packages for others), make sure to also rebuild sys-apps/baselayout.
2. If you install from a binhost, make sure that the binhost is migrated first, and that all clients migrate away from /lib32 immediately. Never let a new client (no /lib32) update from an old binhost (with /lib32).
3. The ancient app-emulation/emul-linux-x86-compat has /lib32 and /usr/lib32 files but is not available anymore. This forced me to keep the symlink /lib32 -> /lib on these servers (they run old Oracle versions).
4. nagios-core's CGI binaries move from /usr/lib to /usr/lib64 and their path is referenced in the Apache configuration.

posted on 2020-11-13 14:32 UTC in Code | 0 comments | permalink