Skip to content

util: make the qsort_r check work on macOS#4765

Merged
ethomson merged 1 commit into
libgit2:masterfrom
tiennou:fix/macos-qsort_r
Aug 26, 2018
Merged

util: make the qsort_r check work on macOS#4765
ethomson merged 1 commit into
libgit2:masterfrom
tiennou:fix/macos-qsort_r

Conversation

@tiennou

@tiennou tiennou commented Aug 14, 2018

Copy link
Copy Markdown
Contributor

As it seems, there are 2 versions of qsort_r (a non-standard function) out there : the BSD version, and the glibc version, and they differ in their parameter ordering (which is quite dangerous because using one for the other will result in runtime failures).

Right now, the defined(BSD) check makes us use the "default" version on macOS, even though it has a BSD implementation available, so the check needs to be weakened. An alternative would be to perform a "BSD-style" compilation check in CMake, and act accordingly.

@tiennou

tiennou commented Aug 14, 2018

Copy link
Copy Markdown
Contributor Author

I found it while looking at the tsort implementation, which has worried Coverity for a loooong time (which I think it's actually safe and Coverity is just paranoid). As a heads-up, I've also closed as Intentional some of the defects there (around git_buf_oom usage, and some of the ones I remember taking a hard look at).

Comment thread src/util.c Outdated
}

#if defined(HAVE_QSORT_S) || (defined(HAVE_QSORT_R) && defined(BSD))
#if defined(HAVE_QSORT_S) || (defined(HAVE_QSORT_R) && !defined(__GLIBC__))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I feel a bit uneasy with this change. !defined(__GLIBC__) is much broader than defined(BSD), and I don't really know whether it'll break any weird platforms. Shouldn't we instead just add another check for macOS in particular?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

TL;DR every platform is weird 😉. I think it's doable to make a CHECK_C_COMPILE test in CMake that would detect the parameter ordering, which would make it at least C-library-resistant (that's the alternative I proposed).

AFAICT, here is what I've been able to gather :

  • qsort_r only exists in FreeBSD/DragonFly, ie. it's not really defined(BSD), and percolated through to macOS.
  • Windows has a qsort_s version.
  • This was helpful comment, as well as this one.

I'll try to see how doable it is to detect all those qsort-ses using compilation checks.

Comment thread src/util.c Outdated
#if defined(HAVE_QSORT_R) && defined(BSD)
#if defined(HAVE_QSORT_R) && defined(__GLIBC__)
qsort_r(els, nel, elsize, cmp, payload);
#elif defined(HAVE_QSORT_R)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Same applies here, I guess

@tiennou tiennou force-pushed the fix/macos-qsort_r branch 3 times, most recently from 7e3cffb to 9955328 Compare August 17, 2018 16:53
@tiennou

tiennou commented Aug 17, 2018

Copy link
Copy Markdown
Contributor Author

Rebased, checking the prototype is done at compile-time now.

Comment thread src/CMakeLists.txt Outdated
" HAVE_QSORT_R_BSD)
IF (HAVE_QSORT_R_BSD)
ADD_DEFINITIONS(-DHAVE_QSORT_R_BSD)
ENDIF ()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Just so that I'm certain that I understand - the idea here is that we're redefining qsort_r, which will be a failure if we're redefining it with a different prototype? So this will fail to compile on glibc-based systems which have said different prototype, and will successfully compile (albeit, I should think, with a warning) on BSD based systems, where we're redefining it, though with the same prototype.

This is clever. I wonder if we could make a cmake module for it, though, that does the whole QSORT_R and type-of-qsort_r check?

Comment thread src/CMakeLists.txt Outdated
" HAVE_QSORT_R_BSD)
IF (HAVE_QSORT_R_BSD)
ADD_DEFINITIONS(-DHAVE_QSORT_R_BSD)
ENDIF ()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think this approach is a lot more sensible. than what we currently have. I'd like to propose a few changes, though:

  • instead of defining HAVE_QSORT_R, only ever define HAVE_QSORT_R_BSD and HAVE_QSORT_R_GNU (and adjust locations using the previous define accordingly)
  • instead of CHECK_C_SOURCE_COMPILES and/or CHECK_FUNCTION_EXISTS, we should be using CHECK_PROTOTYPE_DEFINITION

So, something like this:

CHECK_PROTOTYPE_DEFINITION(qsort_r
	"void qsort_r(void *base, size_t nmemb, size_t size, void *thunk, int (*compar)(void *, const void *, const void *))"
	"NULL" "stdlib.h" HAVE_QSORT_R_BSD)
CHECK_PROTOTYPE_DEFINITION(qsort_r
	"void qsort_r(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *, void *), void *arg)"
	"NULL" "stdlib.h" HAVE_QSORT_R_GNU)

The only thing is that we'd have to include CheckPrototypeDefinition, which is only available since CMake v3.0. There's nothing speaking against distributing it in our cmake/Modules directory, though.

This performs a compile-check by using CMake support, to differentiate the GNU
version from the BSD version of qsort_r.

Module taken from 4f252abea5f1d17c60f6ff115c9c44cc0b6f1df6, which I've checked
against CMake 2.8.11.
@tiennou tiennou force-pushed the fix/macos-qsort_r branch from 9955328 to 1a9cc18 Compare August 24, 2018 20:01
@tiennou

tiennou commented Aug 24, 2018

Copy link
Copy Markdown
Contributor Author

Rebased, and changed to use the CMake module, which I lifted from this. I've tested 2.8.11, and it's okay with configuring that, but it didn't build though :

clang: error: no such file or directory: '/Users/tiennou/Projects/libgit2/_build/deps/http-parser/libgit2.build/Debug/http-parser.build/Objects-normal/undefined_arch/http_parser.o'

undefined_arch makes me think that it doesn't support Xcode 9 😉.

@ethomson

Copy link
Copy Markdown
Member

Thanks for the fix, and the research on the supportedness of qsort_r throughout BSD, @tiennou.

@ethomson ethomson merged commit df2f276 into libgit2:master Aug 26, 2018
@tiennou tiennou deleted the fix/macos-qsort_r branch August 26, 2018 15:07
@pks-t

pks-t commented Aug 27, 2018 via email

Copy link
Copy Markdown
Member

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants