I’m running into a strange issue where GI_TYPELIB_PATH is only set in the first tab of gnome-terminal, but not any additional tabs. It also is not set in non-GUI ttys (i.e. in a shell after Ctrl+Alt+F1) and Console terminal, but it is set in XTerm.

A couple of questions. First, where is GI_TYPELIB_PATH env variable set? I see that my gnome-shell pid has it:

$ ps -eo pid,cmd|rg gnome-shell
  87080 /nix/store/88xzg8if7jxwwf2agr4j5hiz4jf2ynbq-gnome-shell-43.3/bin/gnome-shell
$ grep GI_TYPELIB_PATH= /proc/87080/environ
grep: /proc/87080/environ: binary file matches

so should be pretty high up, but I was not able to find it in the usual places.

Second, what would unset it (and specifically why only for 2nd and subsequent tabs of gnome-terminal)?

Since environment variables are inherited by child processes by most widely used exec functions, it will come from any package in the process tree that sets the variable in a wrapper. Usually, this is done by the confluence of wrapGAppsHook and gobject-introspection dependencies. gnome-shell is indeed the usual suspect.

It is an unfortunate consequence of environment inheritance and should not be relied on. If you need typelibs, e.g. for your own scripts, you should explicitly declare them. Here is an example from my shell history:

$ env XDG_DATA_DIRS= GI_TYPELIB_PATH= nix-shell -I nixpkgs=$HOME/Projects/nixpkgs -p glib gdk-pixbuf gnome-desktop gobject-introspection 'python3.withPackages(ps: with ps; [ pygobject3 ])' --run 'python3 -c "from gi.repository import GnomeDesktop; i = GnomeDesktop.XkbInfo(); print(i.get_layouts_for_country(\"CZE\"))"'

It is difficult to tell why since there are many components that modify the shell environment. GNOME Terminal does it somewhat, though I am not aware of it affecting GI_TYPELIB_PATH. Your shell’s profile script might also affect it, as can various project hooks (e.g. if you use direnv, though direnv usually preserves the original environment).

Thanks for the helpful pointers!

Wait, you’re saying this is built in into the gnome shell wrapper executable at build time? And yeah that looks to be it:

$ grep GI_TYPELIB_PATH /nix/store/88xzg8if7jxwwf2agr4j5hiz4jf2ynbq-gnome-shell-43.3/bin/gnome-shell
grep: /nix/store/88xzg8if7jxwwf2agr4j5hiz4jf2ynbq-gnome-shell-43.3/bin/gnome-shell: binary file matches

I learn something every day…

So there’s no way to do it on a system level? I frequently run scripts from multiple projects in multiple terminals and I’d not like to repeat the declarations from each of them if possible.

Any idea how I could debug this?

Just curios - does this happen on your end? It’s not the only one btw - looks like XDG_DATA_DIRS is another one that is different in the first gnome-terminal tab and the subsequent ones.

Right, but I couldn’t see any useful mention of GI_TYPELIB_PATH in the usual places. /etc/profile, ~/.bash_profile, ~/.profile, ~/.bashrc and what not.

I actually made a script that does /run/current-system/sw/bin/bash -lix &>/tmp/log and made gnome-terminal run it - it did not set it anywhere either from what I see (in either the first or subsequent tabs).

So the only thing that comes to mind right now is the new info you provided about this being embedded into executables, but I’m unsure how that would give different results between tabs. If you have any pointers on how I should debug this, let me know.

Yes, it is the standard workaround for not having central location typelibs could be loaded from. It is not a clean solution but clean ones are much harder to implement (would require manually creating patches for each program that uses gobject-introspection).

You could use environment.sessionVariables option but I would discourage it. It is a sure way to get hard to debug errors from library conflicts whenever you upgrade your system (or when you use software from multiple different Nixpkgs revisions).

See also I installed a library but my compiler is not finding it. Why?

If the projects are under your control, you could create shell.nix/flake.nix files for them, or even have direnv modify the environment transparently whenever you enter the directory.

Or if you own those scripts, you could use nix-shell shebang.

I am unable to reproduce it with new tabs or windows opened from within GNOME Terminal.

But I can reproduce it with new windows opened using a keyboard shortcut that launches gnome-terminal command I set up in Gnome Control Center. Presumably, gsd-media-keys launches the process.

Look at the process tree in htop in tree view (t key) and then environment of each parent process (select a process with cursor keys and then press e key).

Actually, I forgot that GNOME Shell moves the launched children into a scope so it will not be shown directly as child of gnome-shell process. So the process tree might not be as helpful as one would hope.

And while GNOME Shell passes null as the envp argument, so the child processes will inherit the environment, that only applies for processes executed directly. Most modern programs (for example GNOME Console but not GNOME Terminal) are executed using D-Bus activation so that does not apply here – they would get the environment of systemd --user service.

Also notice that in the process tree, there is only gnome-terminal-server, while both the desktop file and my shortcut launch gnome-terminal. Going by the symptoms, it sounds like the shell is launched by gnome-terminal and inherits whatever environment it inherited from its parent and then the shell is that reparented under gnome-terminal-server, obscuring the original process tree.

I guess you could attach strace to gnome-shell and other components and see how it launches gnome-terminal. But otherwise, I do not see other way than digging through the source code of relevant components.

1 Like

@jtojnar Thanks so much for a lot of great information! I’ll try some of your suggestions to see if I can figure out something more and I’ll report here if so.

Is there a way to do this with the new nix shell instead? I tried:

env XDG_DATA_DIRS= GI_TYPELIB_PATH= nix shell nixpkgs#glib nixpkgs#gdk-pixbuf nixpkgs#gnome-desktop nixpkgs#gobject-introspection -c bash -c 'echo $GI_TYPELIB_PATH'

but GI_TYPELIB_PATH is still empty.

The XY problem: I’m using flakes and I want to use the same dependency versions as the system flake.lock. I don’t know how to do that with nix-shell and I’d rather move to “new” commands anyway if possible.

nix shell is mostly for running programs, not providing libraries, so it mainly just sets PATH environment variable. Use nix develop for a shell that is meant for development (so it is library-aware):

nix develop --impure --expr 'let pkgs = import (builtins.getFlake "nixpkgs") {}; in pkgs.mkShell { nativeBuildInputs = with pkgs; [ gobject-introspection ]; buildInputs = with pkgs; [ gnome-desktop ]; }' -c bash -c 'echo $GI_TYPELIB_PATH'
1 Like

Ah, OK, got it - thanks again for the info!