[Bug 1926139] Re: dhclient: thread concurrency race leads to DHCPOFFER packets not being received
Mauricio Faria de Oliveira
1926139 at bugs.launchpad.net
Thu Jan 19 03:53:31 UTC 2023
Hi Matthew,
Thanks for the excellent analysis and considerate fix proposal, as
always!
I looked at this for the last couple of days, for potential sponsorship.
I have attentively gone through the SRU template and Other Info section,
and considered the proposal to switch bind9-libs into --disable-threads,
with the goal of not only address this issue, but also prevent others:
> So, we have two options for a fix for Focal and Jammy:
>
> 1) We disable threading for dhclient.
> 2) We add in a mutex to resolve this particular concurrency issue.
> [...]
> I think if we fix the problem, another issue will crop up in six months
> time, and it will be another concurrency issue.
...
I'm aware you realize such change is concerning :) thus explained it
well.
Changing this is Focal (around for almost 3 years) brings regression risk
to an amount I have the _impression_ the SRU team would not be okay with.
And even though I agree with your analysis, proposal and risk assessment,
I'm a bit concerned too, specially as this touches DHCP / IP addressing.
(I'm also very aware this is ultimately their call, not mine at all. :)
...
However, considering how much work and time have likely gone into this
(and internal status) I can't just say 'no' without trying to help out.
I'd like to bring a different opinion.
The reason it's concerning is the very same reason 2) is reasonable:
This concurrency issue (and potential for other concurrency issues)
has been around with Focal since 2020/04 (~3 years), and until now,
its impact does not seem to statistically significant:
> This happens about once every 100 reboots on bare metal, or [...]
> affecting between ~0.3% to 2% of deployments on Microsoft Azure.
So, if there's a way to fix this particular concurrency issue with
less regression risk, that might be worth it, as it would build on
top of dhclient's life on Focal, instead of starting it over again.
...
So, while reviewing the source code for your analysis, I had ideas.
First, a synthetic reproducer with GDB that works every time.
Second, a patch that addressed the issue with the test above.
(It's not final form, I'd like to add a way to turn it off.)
...
Could you please review and verify both, and share your
thoughts on possibly going with that proposal instead?
Of course, if you disagree with the argument or approach,
or if turns out not to work on your end/tests, that's OK!
We would defer this to the Foundations team and SRU team.
- Test steps in the next comment.
- Test packages in ppa:mfo/lp1926139 [1].
- Debdiff attached for reference (code has details).
(Right now only Focal patches/packages are available.
I can go look at Jammy depending on your feedback.)
Hope this helps, after all.
Thanks again!
[1] https://launchpad.net/~mfo/+archive/ubuntu/lp1926139
--
You received this bug notification because you are a member of Ubuntu
Foundations Bugs, which is subscribed to isc-dhcp in Ubuntu.
https://bugs.launchpad.net/bugs/1926139
Title:
dhclient: thread concurrency race leads to DHCPOFFER packets not being
received
Status in bind9-libs package in Ubuntu:
Fix Released
Status in isc-dhcp package in Ubuntu:
Invalid
Status in bind9-libs source package in Focal:
In Progress
Status in bind9-libs source package in Jammy:
In Progress
Bug description:
[Impact]
Occasionally, during instance boot or machine start-up, dhclient will
attempt to acquire a dhcp lease and fail, leaving the instance with no
IP address and making it unreachable.
This happens about once every 100 reboots on bare metal, or Chris
Patterson in comment #2 describes it as affecting between ~0.3% to 2%
of deployments on Microsoft Azure. Azure uses dhclient called from
cloud-init instead of systemd-networkd, and this is causing issues
with larger deployments.
The logs of an affected dhclient produce the following:
Listening on LPF/enp1s0/52:54:00:1c:d7:00
Sending on LPF/enp1s0/52:54:00:1c:d7:00
Sending on Socket/fallback
DHCPDISCOVER on enp1s0 to 255.255.255.255 port 67 interval 3 (xid=0xd222950f)
DHCPDISCOVER on enp1s0 to 255.255.255.255 port 67 interval 5 (xid=0xd222950f)
...
(omitting 20 similar lines)
...
DHCPDISCOVER on enp1s0 to 255.255.255.255 port 67 interval 13 (xid=0xd222950f)
DHCPDISCOVER on enp1s0 to 255.255.255.255 port 67 interval 8 (xid=0xd222950f)
DHCPDISCOVER on enp1s0 to 255.255.255.255 port 67 interval 6 (xid=0xd222950f)
No DHCPOFFERS received.
No working leases in persistent database - sleeping.
Full log: https://paste.ubuntu.com/p/8yBfw2KR5h/
Log of a working run: https://paste.ubuntu.com/p/N3ZgqrxyQD/
The bizarre thing is when you tcpdump dhclient, we see all DHCPDISOVER
packets being replied to with DHCPOFFER packets, but the got_one()
callback is never called, dhclient does not read these DHCPOFFER
packets, and continues sending DHCPDISCOVER packets. Once it reaches
25 DHCPDISCOVER packets sent, it gives up.
tcpdump: https://bugs.launchpad.net/ubuntu/+source/isc-dhcp/+bug/1926139/+attachment/5641810/+files/test.pcap
Screenshot of Wireshark: https://bugs.launchpad.net/ubuntu/+source/isc-dhcp/+bug/1926139/+attachment/5641811/+files/Screenshot_2023-01-17-16-14-21_1920x1200%250A1920x1080%250A1920x1080.png
This behaviour led several bug reporters to believe it was a kernel
issue, with the kernel not pushing DHCPOFFER packets to dhclient. This
is not the case, the actual problem is dhclient containing a thread
concurrency race condition, and when the race occurs, the read socket
is closed prematurely, and dhclient does not read any of the DHCPOFFER
replies.
The full explanation is in the "Other Info" section, but the fix for
this is to change bind9-libs from being built multithreaded, back to
single threaded as intended by dhclient maintainers.
In Focal and Jammy, isc-dhcp links against bind9 libraries provided in
bind9-libs, while in Kinetic onward isc-dhcp has an in-tree bind9
library it uses, which is already configured properly to --disable-
threads.
Change the Focal and Jammy bind9-libs to --disable-threads and update
symbol files to reflect the library is single threaded again.
[Testcase]
Start a fresh Focal or Jammy instance.
Download and set executable test-parallel.sh, and edit some lines:
1) wget https://bugs.launchpad.net/ubuntu/+source/isc-dhcp/+bug/1926139/+attachment/5593045/+files/test-parallel.sh
2) chmod +x test-parallel.sh
3) vim test-parallel.sh
Change iface="enp5s0" to your interface, likely iface="enp1s0".
Comment out the line "# cp bionic-dhclient $workdir/dhclient".
4) sudo ./test-parallel.sh
After five minutes, if you issue reproduces, you will see "TEST
FAILED".
You can watch the output with:
5) cat /tmp/dhclient-* | less
Next, for instrumented runs, you need to build dhclient from source.
1) sudo apt install build-essential devscripts
2) apt source isc-dhcp
3) sudo apt build-dep isc-dhcp
4) cd isc-dhcp
Apply the below patch:
https://paste.ubuntu.com/p/hGsssrVyG4/
5) patch -p1 < ~/patch.patch
6) debuild -b -uc -us
7) cd ..
8) sudo dpkg -i isc-dhcp-client-*
9) sudo ./test-parallel.sh
10) cat /tmp/dhclient-* | less
Look for the race, as described in "Other Info", namely:
mruffell: registering with socket manager
mruffell: callback called
mruffell: omapi object is NULL
mruffell: omapi object is NULL
mruffell: Adding obj to linked list
mruffell: Obj added to list
The issue has reproduced.
If you install the test package from the following ppa:
https://launchpad.net/~mruffell/+archive/ubuntu/sf337873-test
Instructions to install (on a Focal or Jammy system):
1) sudo add-apt-repository ppa:mruffell/sf337873-test
2) sudo apt update
3) sudo apt install libdns-export1109 libisc-export1105
4) sudo apt-cache policy libisc-export1105 | grep Installed
Installed: 1:9.11.16+dfsg-3~ubuntu1+sf337873v20230116b2
You will notice the issue no longer reproduces.
You can also check to see if dhclient runs as multithreaded by:
$ ps aux | grep dhclient
<look for PID>
$ sudo ps -T -p 19512
PID SPID TTY TIME CMD
19512 19512 ? 00:00:00 dhclient
19512 19519 ? 00:00:00 isc-worker0000
19512 19521 ? 00:00:00 isc-socket
19512 19522 ? 00:00:00 isc-timer
When single threaded, the output should be:
$ sudo ps -T -p 23894
PID SPID TTY TIME CMD
23894 23894 ? 00:00:00 dhclient
[Where problems could occur]
We are changing the configuration of bind9-libs for Focal and Jammy
from a net --enable-threads, to --disable-threads. This will remove
multithreading for bind9-libs and all applications that link to it.
bind9-libs only services isc-dhcp, as per apt rdepends in the "Other
Info" section, and the package was only introduced as a way to get
isc-dhcp to build with older bind9 libs, and avoid having bind9 in-
tree.
In Kinetic onward, the bind9 libs are shipped in-tree for isc-dhcp,
and bind9-libs was removed from the archive.
Since we are only affecting isc-dhcp, we won't affect users of other
packages, unless they for some reason decided to link against
bind9-libs instead of the actual bind9 in the archive.
dhclient was never written for thread concurrency, shown by the lack
of any synchronisation primitives whatsoever, and won't be negatively
affected by going back to being single threaded, as it is in all other
Ubuntu releases.
We are editing the symbol files to remove exported library calls. I
have manually grep'd the isc-dhcp source, and those functions are not
used, but for any users that got confused and link against bind9-libs,
they might be affected by the change. For them, they need to link
against the actual bind9 in the archive.
[Other info]
I was reading around the upstream issue trackers, and found the
following two bug reports:
https://gitlab.isc.org/isc-projects/dhcp/-/issues/264
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=996356
The ISC upstream report was actually quite detailed, and it has the
same symptoms of what we are experiencing.
Let's have a look at the root cause. The code I am using is isc-dhcp
4.4.1-2.1ubuntu5.20.04.4 from Focal.
common/discover.c
567 void
568 discover_interfaces(int state) {
...
1002 case AF_INET:
1003 default:
1004 status = omapi_register_io_object((omapi_object_t *)tmp,
1005 if_readsocket,
1006 0, got_one, 0, 0);
1007 break;
1008 }
...
In discover.c, we call discover_interfaces() to iterate over the
interfaces, and attempt to register a raw socket against it. We do
this by calling omapi_register_io_object() which is used for reading
data, and calls the elusive got_one() callback that you instrumented
your code to see if it was being called or not.
omapip/dispatch.c
196 /* Register an I/O handle so that we can do asynchronous I/O on it. */
197
198 isc_result_t omapi_register_io_object (omapi_object_t *h,
199 int (*readfd) (omapi_object_t *),
200 int (*writefd) (omapi_object_t *),
201 isc_result_t (*reader)
202 (omapi_object_t *),
203 isc_result_t (*writer)
204 (omapi_object_t *),
205 isc_result_t (*reaper)
206 (omapi_object_t *))
207 {
...
241 /*
242 * Attach the I/O object to the isc socket library via the
243 * fdwatch function. This allows the socket library to watch
244 * over a socket that we built. If there are both a read and
245 * a write socket we asssume they are the same socket.
246 */
247
248 if (readfd) {
249 fd_flags |= ISC_SOCKFDWATCH_READ;
250 fd = readfd(h);
251 }
...
257
258 if (fd_flags != 0) {
259 status = isc_socket_fdwatchcreate(dhcp_gbl_ctx.socketmgr,
260 fd, fd_flags,
261 omapi_iscsock_cb,
262 obj,
263 dhcp_gbl_ctx.task,
264 &obj->fd);
...
275 }
276
277
278 /* Find the last I/O state, if there are any. */
279 for (p = omapi_io_states.next;
280 p && p -> next; p = p -> next)
281 ;
282 if (p)
283 omapi_io_reference (&p -> next, obj, MDL);
284 else
285 omapi_io_reference (&omapi_io_states.next, obj, MDL);
...
omapi_register_io_object() is called for each socket created, in this
case, the if_readsocket from discover_interfaces(). The file
descriptor is assigned ISC_SOCKFDWATCH_READ, and we enter the if
statement.
The if statement calls isc_socket_fdwatchcreate(), which registers the
socket with the ISC socket manager, and sets up the callback
omapi_iscsock_cb(), to be called.
Once that has been done, we iterate over the omapi_io_states linked
list, which is a global list of registered sockets. We get to the end
of the list (or the beginning, if the list is empty), and add the
socket to the list.
Now, the bug happens between calling isc_socket_fdwatchcreate() to
register the socket with the socket manager, and adding it to the
global linked list.
Sometimes, the callback omapi_iscsock_cb() is called inbetween.
omapip/dispatch.c
101 /*
102 * Callback routine to connect the omapi I/O object and socket with
103 * the isc socket code. The isc socket code will call this routine
104 * which will then call the correct local routine to process the bytes.
105 *
106 * Currently we are always willing to read more data, this should be modified
107 * so that on connections we don't read more if we already have enough.
108 *
109 * If we have more bytes to write we ask the library to call us when
110 * we can write more. If we indicate we don't have more to write we need
111 * to poke the library via isc_socket_fdwatchpoke.
112 */
...
118 #define SOCKDELETE 1
119 int
120 omapi_iscsock_cb(isc_task_t *task,
121 isc_socket_t *socket,
122 void *cbarg,
123 int flags)
124 {
...
132 #if SOCKDELETE
133 /*
134 * walk through the io states list, if our object is on there
135 * service it. if not ignore it.
136 */
137 for (obj = omapi_io_states.next; obj != NULL; obj = obj->next) {
138 if (obj == cbarg)
139 break;
140 }
141
142 if (obj == NULL) {
143 return(0);
144 }
145 #else
...
164 if ((flags == ISC_SOCKFDWATCH_READ) &&
165 (obj->reader != NULL) &&
166 (obj->inner != NULL)) {
167 status = obj->reader(obj->inner);
168 /*
169 * If we are shutting down (basically tried to
170 * read and got no bytes) we don't need to try
171 * again.
172 */
173 if (status == ISC_R_SHUTTINGDOWN)
174 return (0);
175 /* Otherwise We always ask for more when reading */
176 return (1);
...
188 /*
189 * We get here if we either had an error (inconsistent
190 * structures etc) or no more to write, tell the socket
191 * lib we don't have more to do right now.
192 */
193 return (0);
194 }
When omapi_iscsock_cb() is called, we iterate over that same
omapi_io_states global linked list, and since the raw socket we are
about to add is the very first item going to be placed on the list,
omapi_io_states.next will be NULL, making obj set to NULL. Well what
happens when obj is NULL? We return 0.
142 if (obj == NULL) {
143 return(0);
144 }
If you look down the code a little further, we see that if we are
finished with the socket, like shutting down, or an error happens, we
return 0 to indicate that we are done with this socket, and won't be
needing it anymore, and won't be using it again.
If we return 1, then we ask for more data later on, and
omapi_iscsock_cb() will be called again in the future.
So, by returning 0, we will no longer read any packets from the
socket, and thus, we simply ignore and will never read any DHCPOFFER
packets.
We obviously have two sockets open, one for reading and one for
writing, since one is bound to port 67 and the other to port 68, so we
keep sending out DHCPDISCOVER packets, not knowing we are ignoring all
DHCPOFFERS due to the read socket being closed and not calling
omapi_iscsock_cb() ever again.
So, as explained on the upstream bug, what is needed for this race
condition to occur?
1) There needs to be data that can be read immediately by the socket. This is how omapi_iscsock_cb() is called, when there is data waiting. If there is no data to read, then the race can't happen.
2) Thread scheduling must occur in a particular order.
There are three threads:
a. The main thread, which is registering the socket
b. The socket manager coordinator thread
c. A socket manager worker thread
For the race to occur, we need to switch from a) to b) to schedule the
callback, b) to c) to call the callback and return 0, all before we
return from c) to a) to add the socket to the omapi_io_states linked
list.
To verify this, I added some print statements to omapi_iscsock_cb()
and omapi_register_io_object() to see what is happening:
https://paste.ubuntu.com/p/hGsssrVyG4/
I instrumented entry to the callback, as well as if obj is NULL, and
before and after the socket is registered to the socket manager, and
before and after the socket is added to the global linked list.
I built the new dhclient, and ran test-parallel.sh, since it by far is
the best at reproducing the issue. I concatenated all 20
/tmp/dhclient-* logs to read:
https://paste.ubuntu.com/p/VddddSmdMV/
If we look at one that works and gets the DHCPOFFER, we see:
https://paste.ubuntu.com/p/dfdvNM3RDd/
We have two sockets, one that reads and one that writes. It registers
with the socket manager, adds the socket to the linked list, for both
sockets, one after the other, and then the DHCPDISOVER is set, and
then callbacks are called.
Now, when the issue reproduces:
https://paste.ubuntu.com/p/77BNNhDwdh/
We see that we register the read socket with the socket manager, and
immediately get a callback to omapi_iscsock_cb(), so there is likely a
packet to read already. We return NULL, since the socket is not on the
linked list yet, and strangely this happens twice when we have only
entered omapi_iscsock_cb() once. We then add the socket to the linked
list, showing we have hit the race condition. The writer socket is
added to the socket manager, but does not race, as it is added to the
linked list before the callback happens. The callback only seems to be
called for the writer socket, and we ignore all DHCPOFFER packets,
only sending DHCPDISCOVER packets.
I ran the test-parallel.sh script a few times, and each and every time
the issue reproduced, we had a NULL linked list, and returned 0 from
omapi_iscsock_cb(). So I am confident we have come across the root
cause.
Now, I had an idea of adding a sleep between registering to the socket
manager and adding the socket to the linked list, to try and get every
single agent to fail 100% of the time, hoping that the callback would
be called first.
The change is something like the likes of below:
https://paste.ubuntu.com/p/8zJ2FQK99X/
But after I built it and ran it a few times, I couldn't reproduce the
issue at all. A typical run is below:
https://paste.ubuntu.com/p/k6wRhx4RCM/
We can see that everything happens in the correct order, and the issue
is not reproduced. I think because each dhclient has to wait 2 seconds
before sending a DHCPDISCOVER, the network is quiet, and there is no
packet to read immediately, since neighboring agents are also quiet,
so the callback is not called, and the socket is added to the linked
list before the network gets busy.
The code itself to add the socket to the linked list was added in the
below commit, 22 years ago:
commit 61b844bfd7641a62d681a1f70d3b6dbc485ce4b6
From: Ted Lemon <source at isc.org>
Date: Thu, 2 Sep 1999 00:32:56 +0000
Subject: Omapi library, initial checkin
Link: https://gitlab.isc.org/isc-projects/dhcp/-/commit/61b844bfd7641a62d681a1f70d3b6dbc485ce4b6
Later on, the registration to the socket manager and the callback was
added 13 years ago:
commit 98bf16077d22f28e288a18e184a9d1f97cb5f4f7
From: Shawn Routhier <sar at isc.org>
Date: Wed, 28 Oct 2009 04:12:30 +0000
Subject: Support for asynchronous ddns per ticket 19216 - convert to
using isclib and dnslib.
Link: https://gitlab.isc.org/isc-projects/dhcp/-/commit/98bf16077d22f28e288a18e184a9d1f97cb5f4f7
Finally, the null linked list check in the callback that returns 0 was
also added 13 years ago:
commit 8fa0112dd11ee301046b42fe463074b067e61a35
From: Shawn Routhier <sar at isc.org>
Date: Thu, 19 Nov 2009 23:49:57 +0000
Subject: Ticket 20540 - clean ups for DHCP-DDNS work, add an change
dropped in the merge, arrange to handle callbacks from the socket code after
we've deleted the socket and deal with the quantum issue in the tasks. This
last will be removed shortly as a better fix is now available.
Link: https://gitlab.isc.org/isc-projects/dhcp/-/commit/8fa0112dd11ee301046b42fe463074b067e61a35
This code and thus the bug is present in all versions of Ubuntu from
10.04 LTS onward.
However, I could not reproduce on Bionic, Kinetic or Lunar, so I
looked into why this only seems to affect Focal and Jammy, when all
versions share the same buggy code.
It appears that Focal and Jammy dhclient is multithreaded:
$ sudo ps -T -p 19512
PID SPID TTY TIME CMD
19512 19512 ? 00:00:00 dhclient
19512 19519 ? 00:00:00 isc-worker0000
19512 19521 ? 00:00:00 isc-socket
19512 19522 ? 00:00:00 isc-timer
While on Bionic, Kinetic and Lunar, it presents only a single thread:
$ sudo ps -T -p 23894
PID SPID TTY TIME CMD
23894 23894 ? 00:00:00 dhclient
You can't have thread concurrency issues if you run as a single
thread. The race conditions simply did not happen, since everything
had to execute in order, which is why this bug has existed for 13
years in its current form.
Chris Patterson in comment #2 mentions when he built dhclient from the
latest Debian source, available here:
https://salsa.debian.org/debian/isc-dhcp/-/commits/master/debian
Chris mentions that it solves the problem, and that it uses in-tree
bind libraries. Looking into this, we see the tree has bind 9.11.36:
https://salsa.debian.org/debian/isc-
dhcp/-/blob/master/bind/version.tmp
and its makefile explicitly shows threads being disabled:
https://salsa.debian.org/debian/isc-
dhcp/-/blob/master/bind/Makefile.in
bindconfig =
...
--disable-threads
...
bind 9.11.36 still supports disabling threads. Hence this is how the
upstream debian build did not reproduce the issue on Focal, since
threading was disabled and dhclient ran as a single thread.
On Kinetic and Lunar, the isc-dhcp package seems to track the debian
upstream version, with the very same in-tree bind libraries, set to
--disable-threads, which is why it is fixed in those versions.
So, we have two options for a fix for Focal and Jammy:
1) We disable threading for dhclient.
2) We add in a mutex to resolve this particular concurrency issue.
2) was the plan, but when I think about it, if dhclient has such a
basic thread concurrency issue, and has had it for 13 years without
anyone noticing, it is a fair chance that this will not be the only
thread concurrency issue.
Looking at the source code, there is no mutexes or semaphores. pthread
isn't even a dependency, and it is not linked in. There is no thread
synchronisation primitives at all.
I think if we fix the problem, another issue will crop up in six
months time, and it will be another concurrency issue.
Now, there is a small issue that isc-dhcp is now officially End Of
Life, and has effectively been abandoned by upstream. You can read
about it in these notices:
https://lists.isc.org/pipermail/dhcp-users/2022-October/022786.html
https://www.isc.org/blogs/isc-dhcp-eol/
Upstream won't fix any more bugs, make any new releases, or even
accept any new commits. They are putting their efforts into isc-kea
now.
In which case, 1) to disabling threading seems better.
But it seems isc-dhcp on Focal and Jammy are both incompatible with
their native bind9 packages, and instead, use the libraries from
bind9-libs, a separate package that packages 9.11.16 for Focal and
9.11.19 for Jammy, to work around the incompatibility issue.
https://launchpad.net/ubuntu/+source/bind9-libs
Looking at the dependencies for isc-dhcp in Focal:
$ apt depends isc-dhcp-client
isc-dhcp-client
Depends: libc6 (>= 2.15)
Depends: libdns-export1109
Depends: libisc-export1105
Depends: debianutils (>= 2.8.2)
Depends: iproute2
Recommends: isc-dhcp-common
Suggests: resolvconf
openresolv
Suggests: avahi-autoipd
Suggests: isc-dhcp-client-ddns
We see we depend on libdns-export1109 and libisc-export1105 from
bind9-libs.
Looking at those reverse dependencies:
$ apt rdepends libisc-export1105
libisc-export1105
Reverse Depends:
Depends: libbind-export-dev (= 1:9.11.16+dfsg-3~ubuntu1)
Depends: isc-dhcp-client
Depends: isc-dhcp-server-ldap
Depends: isc-dhcp-relay
Depends: isc-dhcp-client-ddns
Depends: libisccfg-export163
Depends: libisccc-export161
Depends: libirs-export161
Depends: libdns-export1109
Depends: libbind-export-dev (= 1:9.11.16+dfsg-3~build1)
Depends: isc-dhcp-server
Depends: isc-dhcp-client
Depends: isc-dhcp-server-ldap
Depends: isc-dhcp-relay
Depends: isc-dhcp-client-ddns
Depends: libisccfg-export163
Depends: libisccc-export161
Depends: libirs-export161
Depends: libdns-export1109
Depends: isc-dhcp-client
Depends: isc-dhcp-server
It seems it is only isc-dhcp is a reverse dependency.
So it appears perfectly safe to change bind9-libs from --enable-
threads to --disable-threads.
Looking at their debian/rules files:
https://git.launchpad.net/ubuntu/+source/bind9-libs/tree/debian/rules?h=applied/ubuntu/focal-proposed
https://git.launchpad.net/ubuntu/+source/bind9-libs/tree/debian/rules?h=applied/ubuntu/jammy-devel
We see:
CONFIGURE_COMMON := \
...
--disable-threads \
...
--enable-threads \
...
It appears there has been a mistake when setting up the configure
options, and both --disable-threads and --enable-threads is set.
Because of the way configure is set up --enable-threads will always
win.
The fix would be a one line change, to remove --enable-threads.
Since isc-dhcp is dynamically linked to libdns-export1109 and libisc-
export1105, we would probably not even need to rebuild isc-dhcp, and
instead, only a fix to bind9-libs would be needed.
To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/bind9-libs/+bug/1926139/+subscriptions
More information about the foundations-bugs
mailing list