Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix be2enc and be2dec includes #3720

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

chromatic
Copy link
Member

Attempt to address #3673 . This approach works for me on x86-64 Linux.

@patricklodder patricklodder requested a review from a team November 29, 2024 17:33
@patricklodder patricklodder added bug backport to 1.14 When a maintenance release is done on 1.14, backport this code. labels Nov 29, 2024
patricklodder

This comment was marked as outdated.

Use autoconf probes to see if they're available, and fall back to compat
versions in src/compat/endian.h otherwise.
@chromatic
Copy link
Member Author

I've added them to this commit as well. Thanks for the reminder.

@FierceSkit
Copy link
Contributor

FreeBSD, you say?
That's a VM, I have'nt booted in a long time..

Copy link
Member

@patricklodder patricklodder left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reACK on 7a3ccab

  • arm64 macOS Sonoma tested to work (doesn't have any endian.h)
  • x86_64 linux tested to work (has GNU endian.h but that doesn't have *enc or *dec)

FreeBSD should be the final test as that both has BSD sys/endian.h AND *dec/*enc functions.

@FierceSkit

This comment was marked as resolved.

@chromatic
Copy link
Member Author

Hm, I'm expecting to see something like:

conftest.cpp: In function 'int main()':
conftest.cpp:63:10: error: 'be32dec' was not declared in this scope
   63 |   (void) be32dec;
      |          ^~~~~~~
configure:26889: $? = 1
configure: failed program was:
| /* confdefs.h */
...
| #if HAVE_ENDIAN_H
|                  #include <endian.h>
|                  #elif HAVE_SYS_ENDIAN_H
|                  #include <sys/endian.h>
|                  #endif
| 
| int
| main (void)
| {
| #ifndef be32dec
| #ifdef __cplusplus
|   (void) be32dec;
| #else
|   (void) be32dec;
| #endif
| #endif
| 
|   ;
|   return 0;
| }

Do you have lines like that?

@FierceSkit
Copy link
Contributor

Hm, I'm expecting to see something like:

conftest.cpp: In function 'int main()':
conftest.cpp:63:10: error: 'be32dec' was not declared in this scope
   63 |   (void) be32dec;
      |          ^~~~~~~
configure:26889: $? = 1
configure: failed program was:
| /* confdefs.h */
...
| #if HAVE_ENDIAN_H
|                  #include <endian.h>
|                  #elif HAVE_SYS_ENDIAN_H
|                  #include <sys/endian.h>
|                  #endif
| 
| int
| main (void)
| {
| #ifndef be32dec
| #ifdef __cplusplus
|   (void) be32dec;
| #else
|   (void) be32dec;
| #endif
| #endif
| 
|   ;
|   return 0;
| }

Do you have lines like that?

I'm afraid no..
went over it line by line again but: no.. :/

@patricklodder
Copy link
Member

I was able to reproduce the issue from #3673 on FreeBSD 14.1 and boost 1.85 using the qcow2 distributed file.

Tested with:

./configure --without-gui --enable-c++17 \
            BDB_LIBS="-L/usr/local/lib/db5 -ldb_cxx-5.3" \
            BDB_CFLAGS="-I/usr/local/include/db5"
checking for endian.h... yes
checking for sys/endian.h... yes
...
checking whether be32dec is declared... no
checking whether be32enc is declared... no
checking whether le32dec is declared... no
checking whether le32enc is declared... no

The reason that the declarations aren't found is because we're prioritizing endian.h over sys/endian.h and on FreeBSD14.1 I have both: endian.h does not have enc/dec, but sys/endian.h does.

If I reverse the check order, it does detect the latter, but I have to read up on any potential downsides of doing that. I propose to take a bit more time for this one, and make sure that we don't mess this up, especially since this touches consensus code (indirectly, but still does.)

@chromatic
Copy link
Member Author

Alternate approach: wrap the defines within src/compat/endian.h in a nested check for HAVE_SYS_ENDIAN_H, which has some drawbacks (nested preprocessor checks), but it encapsulates the mess and is still an improvement over what we have now.

I'm leery of reversing the check order because we're vulnerable to any other third-party include changing its own check order.

@patricklodder
Copy link
Member

I'm leery of reversing the check order because we're vulnerable to any other third-party include changing its own check order.

Yes, or add sys/endian.h regardless of endian.h presence - this is what boost seems to do right now, so we already have this problem if we do nothing.

@patricklodder
Copy link
Member

I dug a bit and found that this is what boost does. In short:

if gnu or android or openbsd then endian.h
else if macOS then machine/endian.h
else if bsd then sys/endian.h

i.e. the platform selects which to include, which is nasty. But since there is a dependency on this boost code (at least through boost::chrono) there are very few options:

  1. Make sure to do it the same as boost, so that there will not be any conflicts, or
  2. Stop using those boost libs that require boost/predef/other/endian.h so that a clean implementation can be done

Probably the easiest way forward from where we are with this PR right now is to first do 1, then 2? A pure configure.ac solution on top of what is proposed here is possible, by simply testing the same way boost does on top of the detected presence of endian.h / sys/endian.h (and perhaps add the macOS check to be safe in not trying to doubly declare things)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backport to 1.14 When a maintenance release is done on 1.14, backport this code. bug
Projects
Status: 🪲bugfix
Development

Successfully merging this pull request may close these issues.

3 participants