Commit 17329d17ef2f640c5f03e36351f1e19f43acf108 lint: Add exclusions for libmultiprocess subtree looks suboptimal because it adds exceptions for the entire src/ipc/libmultiprocess/ subtree for a whole class of issues. Because there are a few specific issues currently. Even if they are ok, it means new issues will sneak in src/ipc/libmultiprocess/ unnoticed.
It would be better to either resolve the issues and not exclude src/ipc/libmultiprocess/ from linters or add exceptions for the particular issues mentioned in the commit message, so that newly added issues in the future will be detected.
Here is a patch to resolve the locale-dependent issues:
  0diff --git i/src/ipc/libmultiprocess/example/calculator.cpp w/src/ipc/libmultiprocess/example/calculator.cpp
  1index 4290d68733..6926fb8b57 100644
  2--- i/src/ipc/libmultiprocess/example/calculator.cpp
  3+++ w/src/ipc/libmultiprocess/example/calculator.cpp
  4@@ -1,11 +1,12 @@
  5 // Copyright (c) 2021 The Bitcoin Core developers
  6 // Distributed under the MIT software license, see the accompanying
  7 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
  8 
  9 #include <calculator.h>
 10+#include <charconv>
 11 #include <fstream>
 12 #include <init.capnp.h>
 13 #include <init.capnp.proxy.h> // NOLINT(misc-include-cleaner)
 14 #include <init.h>
 15 #include <iostream>
 16 #include <memory>
 17@@ -41,13 +42,17 @@ static void LogPrint(bool raise, const std::string& message)
 18 int main(int argc, char** argv)
 19 {
 20     if (argc != 2) {
 21         std::cout << "Usage: mpcalculator <fd>\n";
 22         return 1;
 23     }
 24+    int fd;
 25+    if (std::from_chars(argv[1], argv[1] + strlen(argv[1]), fd).ec != std::errc{}) {
 26+        std::cout << argv[1] << " is not a number or is larger than an int\n";
 27+        return 1;
 28+    }
 29     mp::EventLoop loop("mpcalculator", LogPrint);
 30-    const int fd = std::stoi(argv[1]);
 31     std::unique_ptr<Init> init = std::make_unique<InitImpl>();
 32     mp::ServeStream<InitInterface>(loop, fd, *init);
 33     loop.loop();
 34     return 0;
 35 }
 36diff --git i/src/ipc/libmultiprocess/example/example.cpp w/src/ipc/libmultiprocess/example/example.cpp
 37index a4f84c55a7..d0e9458f5c 100644
 38--- i/src/ipc/libmultiprocess/example/example.cpp
 39+++ w/src/ipc/libmultiprocess/example/example.cpp
 40@@ -22,13 +22,13 @@ static auto Spawn(mp::EventLoop& loop, const std::string& process_argv0, const s
 41 {
 42     int pid;
 43     const int fd = mp::SpawnProcess(pid, [&](int fd) -> std::vector<std::string> {
 44         fs::path path = process_argv0;
 45         path.remove_filename();
 46         path.append(new_exe_name);
 47-        return {path.string(), std::to_string(fd)};
 48+        return {path.string(), std::format("{:d}", fd)};
 49     });
 50     return std::make_tuple(mp::ConnectStream<InitInterface>(loop, fd), pid);
 51 }
 52 
 53 static void LogPrint(bool raise, const std::string& message)
 54 {
 55diff --git i/src/ipc/libmultiprocess/example/printer.cpp w/src/ipc/libmultiprocess/example/printer.cpp
 56index ccaed6890c..924c651784 100644
 57--- i/src/ipc/libmultiprocess/example/printer.cpp
 58+++ w/src/ipc/libmultiprocess/example/printer.cpp
 59@@ -1,11 +1,12 @@
 60 // Copyright (c) 2021 The Bitcoin Core developers
 61 // Distributed under the MIT software license, see the accompanying
 62 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 63 
 64 #include <fstream>
 65+#include <charconv>
 66 #include <init.capnp.h>
 67 #include <init.capnp.proxy.h> // NOLINT(misc-include-cleaner)
 68 #include <init.h>
 69 #include <iostream>
 70 #include <memory>
 71 #include <mp/proxy-io.h>
 72@@ -34,13 +35,17 @@ static void LogPrint(bool raise, const std::string& message)
 73 int main(int argc, char** argv)
 74 {
 75     if (argc != 2) {
 76         std::cout << "Usage: mpprinter <fd>\n";
 77         return 1;
 78     }
 79+    int fd;
 80+    if (std::from_chars(argv[1], argv[1] + strlen(argv[1]), fd).ec != std::errc{}) {
 81+        std::cout << argv[1] << " is not a number or is larger than an int\n";
 82+        return 1;
 83+    }
 84     mp::EventLoop loop("mpprinter", LogPrint);
 85-    const int fd = std::stoi(argv[1]);
 86     std::unique_ptr<Init> init = std::make_unique<InitImpl>();
 87     mp::ServeStream<InitInterface>(loop, fd, *init);
 88     loop.loop();
 89     return 0;
 90 }
 91diff --git i/src/ipc/libmultiprocess/src/mp/gen.cpp w/src/ipc/libmultiprocess/src/mp/gen.cpp
 92index c4d9a51675..267c2837a6 100644
 93--- i/src/ipc/libmultiprocess/src/mp/gen.cpp
 94+++ w/src/ipc/libmultiprocess/src/mp/gen.cpp
 95@@ -10,12 +10,13 @@
 96 #include <cstdint>
 97 #include <cstdio>
 98 #include <cstdlib>
 99 #include <errno.h>
100 #include <fstream>
101 #include <functional>
102+#include <iostream>
103 #include <kj/array.h>
104 #include <kj/common.h>
105 #include <kj/filesystem.h>
106 #include <kj/memory.h>
107 #include <kj/string.h>
108 #include <map>
109@@ -634,13 +635,13 @@ static void Generate(kj::StringPtr src_prefix,
110     h << "#endif\n";
111 }
112 
113 int main(int argc, char** argv)
114 {
115     if (argc < 3) {
116-        fprintf(stderr, "Usage: " PROXY_BIN " SRC_PREFIX INCLUDE_PREFIX SRC_FILE [IMPORT_PATH...]\n");
117+        std::cerr << "Usage: " << PROXY_BIN << " SRC_PREFIX INCLUDE_PREFIX SRC_FILE [IMPORT_PATH...]\n";
118         exit(1);
119     }
120     std::vector<kj::StringPtr> import_paths;
121     std::vector<kj::Own<const kj::ReadableDirectory>> import_dirs;
122     auto fs = kj::newDiskFilesystem();
123     auto cwd = fs->getCurrentPath();
124diff --git i/src/ipc/libmultiprocess/src/mp/util.cpp w/src/ipc/libmultiprocess/src/mp/util.cpp
125index 691ae0b34b..15c40b3373 100644
126--- i/src/ipc/libmultiprocess/src/mp/util.cpp
127+++ w/src/ipc/libmultiprocess/src/mp/util.cpp
128@@ -3,12 +3,13 @@
129 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
130 
131 #include <mp/config.h>
132 #include <mp/util.h>
133 
134 #include <errno.h>
135+#include <format>
136 #include <kj/common.h>
137 #include <kj/string-tree.h>
138 #include <pthread.h>
139 #include <sstream>
140 #include <stdio.h>
141 #include <string>
142@@ -82,15 +83,13 @@ std::string LogEscape(const kj::StringTree& string)
143     string.visit([&](const kj::ArrayPtr<const char>& piece) {
144         if (result.size() > MAX_SIZE) return;
145         for (const char c : piece) {
146             if (c == '\\') {
147                 result.append("\\\\");
148             } else if (c < 0x20 || c > 0x7e) {
149-                char escape[4];
150-                snprintf(escape, 4, "\\%02x", c);
151-                result.append(escape);
152+                result.append(std::format("\\{:02x}", c));
153             } else {
154                 result.push_back(c);
155             }
156             if (result.size() > MAX_SIZE) {
157                 result += "...";
158                 break;
159diff --git i/src/ipc/libmultiprocess/test/mp/test/test.cpp w/src/ipc/libmultiprocess/test/mp/test/test.cpp
160index 7721d41ff6..7fc64f6741 100644
161--- i/src/ipc/libmultiprocess/test/mp/test/test.cpp
162+++ w/src/ipc/libmultiprocess/test/mp/test/test.cpp
163@@ -8,12 +8,13 @@
164 #include <mp/test/foo.h>
165 
166 #include <capnp/capability.h>
167 #include <cstdio>
168 #include <future>
169 #include <functional>
170+#include <iostream>
171 #include <memory>
172 #include <kj/common.h>
173 #include <kj/memory.h>
174 #include <kj/test.h>
175 #include <string>
176 #include <thread>
177@@ -24,13 +25,15 @@ namespace test {
178 
179 KJ_TEST("Call FooInterface methods")
180 {
181     std::promise<std::unique_ptr<ProxyClient<messages::FooInterface>>> foo_promise;
182     std::function<void()> disconnect_client;
183     std::thread thread([&]() {
184-        EventLoop loop("mptest", [](bool raise, const std::string& log) { printf("LOG%i: %s\n", raise, log.c_str()); });
185+        EventLoop loop("mptest", [](bool raise, const std::string& log) {
186+            std::cout << "LOG" << raise << ": " << log << "\n";
187+        });
188         auto pipe = loop.m_io_context.provider->newTwoWayPipe();
189 
190         auto connection_client = std::make_unique<Connection>(loop, kj::mv(pipe.ends[0]));
191         auto foo_client = std::make_unique<ProxyClient<messages::FooInterface>>(
192             connection_client->m_rpc_system->bootstrap(ServerVatId().vat_id).castAs<messages::FooInterface>(),
193             connection_client.get(), /* destroy_connection= */ false);
194diff --git i/test/lint/lint-locale-dependence.py w/test/lint/lint-locale-dependence.py
195index 1b1aeffdcb..d84e458bb1 100755
196--- i/test/lint/lint-locale-dependence.py
197+++ w/test/lint/lint-locale-dependence.py
198@@ -48,13 +48,12 @@ KNOWN_VIOLATIONS = [
199     "src/wallet/bdb.cpp:.*DbEnv::strerror",  # False positive
200     "src/util/syserror.cpp:.*strerror",      # Outside this function use `SysErrorString`
201 ]
202 
203 REGEXP_EXTERNAL_DEPENDENCIES_EXCLUSIONS = [
204     "src/crypto/ctaes/",
205-    "src/ipc/libmultiprocess/",
206     "src/leveldb/",
207     "src/secp256k1/",
208     "src/minisketch/",
209     "src/tinyformat.h",
210 ]
211 
And also another one to still run test_runner on src/ipc/libmultiprocess/ but only skip std::filesystem check for example.cpp and the include guard test for the entire src/ipc/libmultiprocess/:
 0diff --git i/test/lint/lint-include-guards.py w/test/lint/lint-include-guards.py
 1index 77af05c1c2..ed10deaa90 100755
 2--- i/test/lint/lint-include-guards.py
 3+++ w/test/lint/lint-include-guards.py
 4@@ -17,12 +17,13 @@ from lint_ignore_dirs import SHARED_EXCLUDED_SUBTREES
 5 
 6 HEADER_ID_PREFIX = 'BITCOIN_'
 7 HEADER_ID_SUFFIX = '_H'
 8 
 9 EXCLUDE_FILES_WITH_PREFIX = ['contrib/devtools/bitcoin-tidy',
10                              'src/crypto/ctaes',
11+                             'src/ipc/libmultiprocess',
12                              'src/tinyformat.h',
13                              'src/bench/nanobench.h',
14                              'src/test/fuzz/FuzzedDataProvider.h'] + SHARED_EXCLUDED_SUBTREES
15 
16 
17 def _get_header_file_lst() -> list[str]:
18diff --git i/test/lint/lint_ignore_dirs.py w/test/lint/lint_ignore_dirs.py
19index 7525eac341..af9ee7ef6b 100644
20--- i/test/lint/lint_ignore_dirs.py
21+++ w/test/lint/lint_ignore_dirs.py
22@@ -1,6 +1,5 @@
23 SHARED_EXCLUDED_SUBTREES = ["src/leveldb/",
24                  "src/crc32c/",
25                  "src/secp256k1/",
26                  "src/minisketch/",
27-                 "src/ipc/libmultiprocess/",
28                 ]
29diff --git i/test/lint/test_runner/src/main.rs w/test/lint/test_runner/src/main.rs
30index fe77a98c29..a633f5d43d 100644
31--- i/test/lint/test_runner/src/main.rs
32+++ w/test/lint/test_runner/src/main.rs
33@@ -284,13 +284,13 @@ fn lint_std_filesystem() -> LintResult {
34         .args([
35             "grep",
36             "--line-number",
37             "std::filesystem",
38             "--",
39             "./src/",
40-            ":(exclude)src/ipc/libmultiprocess/",
41+            ":(exclude)src/ipc/libmultiprocess/example/example.cpp",
42             ":(exclude)src/util/fs.h",
43         ])
44         .status()
45         .expect("command error")
46         .success();
47     if found {