Featured image: Reloadable .conf file

In my previous article about nsswitch.conf I talked about how simple, perhaps too simple, this config file is to use. What I didn't cover then was how simplistic its internal implementation is. Specifically, an application only loads this file once—the first time it's needed.

So, what do you do when nsswitch.conf needs to change? How do you update all of the running applications? You don’t! The only way to force a reload is to stop the application and restart it. That is not always an option, especially for critical applications that might take a long time to restart.

Recent work behind the scenes in the GNU C library will change all of this. As of glibc version 2.33, this config file now reloads and reparses each time it changes, and only the configuration is reloaded. If the configuration calls for an external shared library to be loaded, that object is only ever loaded once. It may be called in a different sequence, or not called at all, but it is never unloaded. This behavior avoids a whole class of problems related to unloading shared objects that might still be in use.

Most applications will never know any of this is happening. They do their lookups and get the data they need, even if it’s different than the last time. Applications that cache their lookups will never know anything changed. The catch is that if an application caches some of its lookups, but not others, it might receive an inconsistent set of information. Applications should already accommodate changes in the data, such as host addresses or the occasional UID update, so changing how that information is provided should not significantly change the application or increase the burden to the programmer.

I’ll address one concern likely to come up—memory. To avoid unrestrained growth in long-running programs, the parser maintains a pool of the pre-parsed lines it’s seen, and an array of the services it provides. It only needs to link the existing bits of data together. However, this practice assumes that the overall number of action permutations is limited. Most systems cycle between a few lines, so the size of this pool is limited, as shown in Figure 1. The data for each shared object is also fixed once the object is loaded.

Create the data for each shared object that is fixed once the object is loaded.
Figure 1: Create the data for each shared object that is fixed once the object is loaded.

Of course, there is one key caveat. Anything that updates nsswitch.conf needs to do it as atomically as possible so that applications don’t see a partial configuration and try to load it. If you are using a tool like rsync to update remote machines (say, in a cluster or compute farm, or across a business unit), make sure you don’t use the --inplace option. You might want to use a create/copy/rename sequence so that glibc doesn’t see a half-copied file.

Last updated: January 13, 2021