later icon indicating copy to clipboard operation
later copied to clipboard

OpenBSD: undefined symbol '_tthread_timespec_get'

Open ghost opened this issue 4 years ago • 11 comments

I recently upgraded from OpenBSD 6.5 to 6.6, which also triggered an upgrade from R 3.5.3 to 3.6.1. Starting with a clean Rlibs, I am unable to install (compile) later, which throws an error about an undefined symbol, _tthread_timespec_get. Online references to this symbol are minimal. All output is below. Otherwise, R was working fine on OpenBSD 6.3-6.5. Please advise on a fix.

install.packages("later") Installing package into ‘/home/sbaig14/Documents/local/share/Rlibs’ (as ‘lib’ is unspecified) trying URL 'http://cran.us.r-project.org/src/contrib/later_1.0.0.tar.gz' Content type 'application/x-gzip' length 56563 bytes (55 KB) ================================================== downloaded 55 KB

  • installing source package ‘later’ ... ** package ‘later’ successfully unpacked and MD5 sums checked ** using staged installation ** libs c++ -std=gnu++11 -I"/usr/local/lib/R/include" -DNDEBUG -pthread -DSTRICT_R_HEADERS -I"/home/sbaig14/Documents/local/share/Rlibs/Rcpp/include" -I"/home/sbaig14/Documents/local/share/Rlibs/BH/include" -I/usr/local/include -fpic -O2 -pipe -c RcppExports.cpp -o RcppExports.o c++ -std=gnu++11 -I"/usr/local/lib/R/include" -DNDEBUG -pthread -DSTRICT_R_HEADERS -I"/home/sbaig14/Documents/local/share/Rlibs/Rcpp/include" -I"/home/sbaig14/Documents/local/share/Rlibs/BH/include" -I/usr/local/include -fpic -O2 -pipe -c callback_registry.cpp -o callback_registry.o c++ -std=gnu++11 -I"/usr/local/lib/R/include" -DNDEBUG -pthread -DSTRICT_R_HEADERS -I"/home/sbaig14/Documents/local/share/Rlibs/Rcpp/include" -I"/home/sbaig14/Documents/local/share/Rlibs/BH/include" -I/usr/local/include -fpic -O2 -pipe -c debug.cpp -o debug.o cc -I"/usr/local/lib/R/include" -DNDEBUG -pthread -DSTRICT_R_HEADERS -I"/home/sbaig14/Documents/local/share/Rlibs/Rcpp/include" -I"/home/sbaig14/Documents/local/share/Rlibs/BH/include" -I/usr/local/include -fpic -O2 -pipe -c init.c -o init.o c++ -std=gnu++11 -I"/usr/local/lib/R/include" -DNDEBUG -pthread -DSTRICT_R_HEADERS -I"/home/sbaig14/Documents/local/share/Rlibs/Rcpp/include" -I"/home/sbaig14/Documents/local/share/Rlibs/BH/include" -I/usr/local/include -fpic -O2 -pipe -c later.cpp -o later.o c++ -std=gnu++11 -I"/usr/local/lib/R/include" -DNDEBUG -pthread -DSTRICT_R_HEADERS -I"/home/sbaig14/Documents/local/share/Rlibs/Rcpp/include" -I"/home/sbaig14/Documents/local/share/Rlibs/BH/include" -I/usr/local/include -fpic -O2 -pipe -c later_posix.cpp -o later_posix.o c++ -std=gnu++11 -I"/usr/local/lib/R/include" -DNDEBUG -pthread -DSTRICT_R_HEADERS -I"/home/sbaig14/Documents/local/share/Rlibs/Rcpp/include" -I"/home/sbaig14/Documents/local/share/Rlibs/BH/include" -I/usr/local/include -fpic -O2 -pipe -c later_win32.cpp -o later_win32.o c++ -std=gnu++11 -I"/usr/local/lib/R/include" -DNDEBUG -pthread -DSTRICT_R_HEADERS -I"/home/sbaig14/Documents/local/share/Rlibs/Rcpp/include" -I"/home/sbaig14/Documents/local/share/Rlibs/BH/include" -I/usr/local/include -fpic -O2 -pipe -c timer_posix.cpp -o timer_posix.o c++ -std=gnu++11 -I"/usr/local/lib/R/include" -DNDEBUG -pthread -DSTRICT_R_HEADERS -I"/home/sbaig14/Documents/local/share/Rlibs/Rcpp/include" -I"/home/sbaig14/Documents/local/share/Rlibs/BH/include" -I/usr/local/include -fpic -O2 -pipe -c timestamp_unix.cpp -o timestamp_unix.o c++ -std=gnu++11 -I"/usr/local/lib/R/include" -DNDEBUG -pthread -DSTRICT_R_HEADERS -I"/home/sbaig14/Documents/local/share/Rlibs/Rcpp/include" -I"/home/sbaig14/Documents/local/share/Rlibs/BH/include" -I/usr/local/include -fpic -O2 -pipe -c timestamp_win32.cpp -o timestamp_win32.o cc -I"/usr/local/lib/R/include" -DNDEBUG -pthread -DSTRICT_R_HEADERS -I"/home/sbaig14/Documents/local/share/Rlibs/Rcpp/include" -I"/home/sbaig14/Documents/local/share/Rlibs/BH/include" -I/usr/local/include -fpic -O2 -pipe -c tinycthread.c -o tinycthread.o c++ -std=gnu++11 -shared -L/usr/local/lib/R/lib -L/usr/local/lib -Wl,-R/usr/local/lib/R/lib -o later.so RcppExports.o callback_registry.o debug.o init.o later.o later_posix.o later_win32.o timer_posix.o timestamp_unix.o timestamp_win32.o tinycthread.o -pthread -L/usr/local/lib/R/lib -lR installing to /home/sbaig14/Documents/local/share/Rlibs/00LOCK-later/00new/later/libs ** R ** inst ** byte-compile and prepare package for lazy loading ** help *** installing help indices ** building package indices ** installing vignettes ** testing if installed package can be loaded from temporary location R:/home/sbaig14/Documents/local/share/Rlibs/00LOCK-later/00new/later/libs/later.so: undefined symbol '_tthread_timespec_get' Error: package or namespace load failed for ‘later’ in dyn.load(file, DLLpath = DLLpath, ...): unable to load shared object '/home/sbaig14/Documents/local/share/Rlibs/00LOCK-later/00new/later/libs/later.so': Cannot load specified object Error: loading failed Execution halted ERROR: loading failed
  • removing ‘/home/sbaig14/Documents/local/share/Rlibs/later’

The downloaded source packages are in ‘/tmp/Rtmpz4Nqfe/downloaded_packages’ Warning message: In install.packages("later") : installation of package ‘later’ had non-zero exit status

ghost avatar Dec 05 '19 22:12 ghost

It looks like this is how it gets defined. If TIME_UTC is not defined, then the following happens in tinycthread.h:

  • _TTHREAD_EMULATE_TIMESPEC_GET_ is defined
  • _tthread_timespec_get is declared in tinycthread.h and the function is defined in tinycthread.c: https://github.com/r-lib/later/blob/3d8648b/src/tinycthread.c#L866-L867
  • timespec_get is defined to be _tthread_timespec_get. (The code in the package calls timespec_get, which gets replaced with _tthread_timespec_get in the C preprocessing stage.) https://github.com/r-lib/later/blob/3d8648b/src/tinycthread.h#L122-L136

In short:

  • The C++ code in later's src/ directory calls timespec_get, and if TIME_UTC is not defined, that gets replaced with _tthread_timespec_get. (When TIME_UTC is defined, then there's no _tthread_timespec_get at all.)

Also note that tinycthread itself is C code, and compiled with cc, while the other code from this package is C++ code and is compiled with c++ -std=gnu++11.

Now, as for OpenBSD, it looks like there was a recent change to time.h, where it defines TIME_UTC and declares timespec_get, but only if __ISO_C_VISIBLE is greater than 2011: https://github.com/openbsd/src/commit/6151004e8c8aaceddcc3cd7708473813e57ddab0#diff-5b9f1c6457e0e10079f657f283c19861R178-R181

#if __ISO_C_VISIBLE >= 2011
#define TIME_UTC	1	/* time elapsed since epoch */
int timespec_get(struct timespec *_ts, int _base);
#endif

I suspect that what's happening is that when later's C++ code is compiled, __ISO_C_VISIBLE is either not set, or it is less than 2001, so TIME_UTC is not set, and the code calls _tthread_timespec_get. However, when tinycthread is compiled with a plain C compiler, __ISO_C_VISIBLE is >= 2011, and so TIME_UTC is set, and _tthread_timespec_get never is defined.

It looks like __ISO_C_VISIBLE is in cdefs.h. When a C++ compiler is used, it needs to be compiled with a C++17 standard for it to set __ISO_C_VISIBLE to 2011. That seems strange to me but I'm sure the OpenBSD people have their reasons for doing that. https://github.com/openbsd/src/blob/43b1a0f66dad6aaa6af8973a4715892bd96965ed/sys/sys/cdefs.h#L377-L379


So to summarize: I believe the link error is happening because the C++ code is being compiled with one C standard, and the C code is being compiled with a different C standard. If I'm right, compiling the C++ code with std=gnu++17 or std=c++17 may make it work.

It's possible that if you create a personal ~/.R/Makevars file, one or more of the following lines will make it work:

CXX_STD=CXX17
CXX=c++ -std=gnu++17
CXXFLAGS=-D__ISO_C_VISIBLE=2011
CXXFLAGS=-std=gnu++17

wch avatar Dec 06 '19 03:12 wch

Hello, I also have this issue on OpenBSD 6.6 with a clean R install. I added the lines suggested above to the ~/.R/Makevars file with no difference unfortunately:

R:/usr/local/lib/R/library/00LOCK-later/00new/later/libs/later.so: undefined symbol '_tthread_timespec_get'
Error: package or namespace load failed for 'later' in dyn.load(file, DLLpath = DLLpath, ...):
 unable to load shared object '/usr/local/lib/R/library/00LOCK-later/00new/later/libs/later.so':
  Cannot load specified object
Error: loading failed
Execution halted
ERROR: loading failed

session info below:

R version 3.6.1 (2019-07-05)
Platform: x86_64-unknown-openbsd6.6 (64-bit)
Running under: OpenBSD myhost.mydomain 6.6 GENERIC.MP#518 amd64

Matrix products: default
BLAS:   /usr/local/lib/R/lib/libRblas.so.35.1
LAPACK: /usr/local/lib/R/lib/libRlapack.so.35.1

locale:
[1] C

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base

loaded via a namespace (and not attached):
[1] compiler_3.6.1 tools_3.6.1

Though based off the output

* installing *source* package 'later' ...                                                                                                                                                 [11/418]
** package 'later' successfully unpacked and MD5 sums checked
** using staged installation
** libs
c++ -std=gnu++11 -I"/usr/local/lib/R/include" -DNDEBUG -pthread -DSTRICT_R_HEADERS -I"/usr/local/lib/R/library/Rcpp/include" -I"/usr/local/lib/R/library/BH/include" -I/usr/local/include  -fpic
-O2 -pipe  -c RcppExports.cpp -o RcppExports.o
c++ -std=gnu++11 -I"/usr/local/lib/R/include" -DNDEBUG -pthread -DSTRICT_R_HEADERS -I"/usr/local/lib/R/library/Rcpp/include" -I"/usr/local/lib/R/library/BH/include" -I/usr/local/include  -fpic
-O2 -pipe  -c callback_registry.cpp -o callback_registry.o
c++ -std=gnu++11 -I"/usr/local/lib/R/include" -DNDEBUG -pthread -DSTRICT_R_HEADERS -I"/usr/local/lib/R/library/Rcpp/include" -I"/usr/local/lib/R/library/BH/include" -I/usr/local/include  -fpic
-O2 -pipe  -c debug.cpp -o debug.o
cc -I"/usr/local/lib/R/include" -DNDEBUG -pthread -DSTRICT_R_HEADERS -I"/usr/local/lib/R/library/Rcpp/include" -I"/usr/local/lib/R/library/BH/include" -I/usr/local/include  -fpic  -O2 -pipe  -c
init.c -o init.o
c++ -std=gnu++11 -I"/usr/local/lib/R/include" -DNDEBUG -pthread -DSTRICT_R_HEADERS -I"/usr/local/lib/R/library/Rcpp/include" -I"/usr/local/lib/R/library/BH/include" -I/usr/local/include  -fpic
-O2 -pipe  -c later.cpp -o later.o
c++ -std=gnu++11 -I"/usr/local/lib/R/include" -DNDEBUG -pthread -DSTRICT_R_HEADERS -I"/usr/local/lib/R/library/Rcpp/include" -I"/usr/local/lib/R/library/BH/include" -I/usr/local/include  -fpic
-O2 -pipe  -c later_posix.cpp -o later_posix.o
c++ -std=gnu++11 -I"/usr/local/lib/R/include" -DNDEBUG -pthread -DSTRICT_R_HEADERS -I"/usr/local/lib/R/library/Rcpp/include" -I"/usr/local/lib/R/library/BH/include" -I/usr/local/include  -fpic
-O2 -pipe  -c later_win32.cpp -o later_win32.o
c++ -std=gnu++11 -I"/usr/local/lib/R/include" -DNDEBUG -pthread -DSTRICT_R_HEADERS -I"/usr/local/lib/R/library/Rcpp/include" -I"/usr/local/lib/R/library/BH/include" -I/usr/local/include  -fpic
-O2 -pipe  -c timer_posix.cpp -o timer_posix.o
c++ -std=gnu++11 -I"/usr/local/lib/R/include" -DNDEBUG -pthread -DSTRICT_R_HEADERS -I"/usr/local/lib/R/library/Rcpp/include" -I"/usr/local/lib/R/library/BH/include" -I/usr/local/include  -fpic
-O2 -pipe  -c timestamp_unix.cpp -o timestamp_unix.o
c++ -std=gnu++11 -I"/usr/local/lib/R/include" -DNDEBUG -pthread -DSTRICT_R_HEADERS -I"/usr/local/lib/R/library/Rcpp/include" -I"/usr/local/lib/R/library/BH/include" -I/usr/local/include  -fpic
-O2 -pipe  -c timestamp_win32.cpp -o timestamp_win32.o
cc -I"/usr/local/lib/R/include" -DNDEBUG -pthread -DSTRICT_R_HEADERS -I"/usr/local/lib/R/library/Rcpp/include" -I"/usr/local/lib/R/library/BH/include" -I/usr/local/include  -fpic  -O2 -pipe  -c
tinycthread.c -o tinycthread.o
c++ -std=gnu++11 -shared -L/usr/local/lib/R/lib -L/usr/local/lib -Wl,-R/usr/local/lib/R/lib -o later.so RcppExports.o callback_registry.o debug.o init.o later.o later_posix.o later_win32.o timer
_posix.o timestamp_unix.o timestamp_win32.o tinycthread.o -pthread -L/usr/local/lib/R/lib -lR
installing to /usr/local/lib/R/library/00LOCK-later/00new/later/libs
** R
** inst
** byte-compile and prepare package for lazy loading
** help
*** installing help indices
** building package indices
** installing vignettes
** testing if installed package can be loaded from temporary location
R:/usr/local/lib/R/library/00LOCK-later/00new/later/libs/later.so: undefined symbol '_tthread_timespec_get'
Error: package or namespace load failed for 'later' in dyn.load(file, DLLpath = DLLpath, ...):
 unable to load shared object '/usr/local/lib/R/library/00LOCK-later/00new/later/libs/later.so':
  Cannot load specified object
Error: loading failed
Execution halted

it doesn't see like it's actually respecting those set compiler flags? I even tried off the R installation and administration manual setting the R_MAKEVARS_USER variable to ~/.R/Makevars to make sure it was picking it up with no success. Any other thoughts? Help much appreciated

tmward avatar Dec 12 '19 17:12 tmward

@tmward I see it's trying to install to /usr/local/lib/R/library/00LOCK-later/00new/later/libs. Are you installing as root? You may need to make sure the ~/.R/Makevars file is in the right place. I'm not that familiar with OpenBSD, but if root's home dir is /root, then you'd need to put it in /root/.R/Makevars. In your R session, you can also check what it thinks the home directory is by calling Sys.getenv('HOME').

wch avatar Dec 12 '19 18:12 wch

@wch I'm installing as a user but have made those directories readable/writeable by my user. The install fails with the same error if I also use my home directory for the R packages. (The reason I installed in /usr/local (which is what R defaults to for OpenBSD), is that /usr/local is the only file mount that allows for processes to ask for writeable and executable and wanted to be sure this was not contributing to the problem).

I checked Sys.getenv('HOME'), it correctly recognizes my home directory

tmward avatar Dec 12 '19 18:12 tmward

I'm at a loss about why it's not reading your Makevars file. Maybe ask on StackOverflow?

wch avatar Dec 12 '19 19:12 wch

I was able to install under openbsd with these makevars (thanks to @wch and this thread):

CXX11 = clang++
CXX11STD = -std=gnu++17

You can find default values in /usr/local/lib/R/etc/Makeconf

semio avatar Dec 14 '19 06:12 semio

Changing my Makevars to what @semio listed worked perfect. Thanks everyone for the help.

tmward avatar Dec 15 '19 17:12 tmward

A follow-up: it looks like with C, timespec_get and TIME_UTC are part of the C11 standard: https://en.cppreference.com/w/c/chrono/timespec_get image

However, with C++, std::timespec_get and TIME_UTC are part of the C++17 standard: https://en.cppreference.com/w/cpp/chrono/c/timespec_get image

So OpenBSD 6.6 appears to be doing things according to spec, thought it's the only platform we've heard about that is this strict about timespec_get being available only with C++17 -- other platforms seem to make it available even when using previous C++ standards.

wch avatar Dec 17 '19 15:12 wch

Let me know if I should open a new Issue

I'm facing a similar problem installing on Termux on a Chromebook. The suggested fixes (edit Makeconf) don't seem to be working when even installing the latest dev version remotes::install_github('r-lib/later').

checking for file ‘/data/data/com.termux/files/usr/tmp/RtmpiFGt8B/remotes163e5ce1d43e/r-lib-later-1f7de58/DESCRIPTION’ ... OK
* preparing ‘later’:
* checking DESCRIPTION meta-information ... OK
* cleaning src
* running ‘cleanup’
* checking for LF line-endings in source and make files and shell scripts
* checking for empty or unneeded directories
* building ‘later_1.0.0.9004.tar.gz’
* installing *source* package ‘later’ ...
** using staged installation
Running configure script
-latomic linker flag needed.
** libs
clang++ -std=gnu++17 -I"/data/data/com.termux/files/usr/lib/R/include" -DNDEBUG -pthread -DSTRICT_R_HEADERS -I"/data/data/com.termux/files/usr/lib/R/library/Rcpp/include" -I"/data/data/com.termux/files/usr/lib/R/library/BH/include" -I/data/data/com.termux/files/usr/include  -fpic  -march=armv7-a -mfpu=neon -mfloat-abi=softfp -mthumb  -D__ISO_C_VISIBLE=2011 -c RcppExports.cpp -o RcppExports.o
clang++ -std=gnu++17 -I"/data/data/com.termux/files/usr/lib/R/include" -DNDEBUG -pthread -DSTRICT_R_HEADERS -I"/data/data/com.termux/files/usr/lib/R/library/Rcpp/include" -I"/data/data/com.termux/files/usr/lib/R/library/BH/include" -I/data/data/com.termux/files/usr/include  -fpic  -march=armv7-a -mfpu=neon -mfloat-abi=softfp -mthumb  -D__ISO_C_VISIBLE=2011 -c callback_registry.cpp -o callback_registry.o
clang++ -std=gnu++17 -I"/data/data/com.termux/files/usr/lib/R/include" -DNDEBUG -pthread -DSTRICT_R_HEADERS -I"/data/data/com.termux/files/usr/lib/R/library/Rcpp/include" -I"/data/data/com.termux/files/usr/lib/R/library/BH/include" -I/data/data/com.termux/files/usr/include  -fpic  -march=armv7-a -mfpu=neon -mfloat-abi=softfp -mthumb  -D__ISO_C_VISIBLE=2011 -c debug.cpp -o debug.o
In file included from callback_registry.cpp:5:
In file included from ./callback_registry.h:11:
./threadutils.h:119:9: error: use of undeclared identifier 'timespec_get'; did you mean 'timespec'?
    if (timespec_get(&ts, TIME_UTC) != TIME_UTC) {
        ^
/data/data/com.termux/files/usr/include/linux/time.h:24:8: note: 'timespec' declared here
struct timespec {
       ^
1 error generated.
make: *** [/data/data/com.termux/files/usr/lib/R/etc/Makeconf:177: callback_registry.o] Error 1
make: *** Waiting for unfinished jobs....
ERROR: compilation failed for package ‘later’

ChiWPak avatar May 08 '20 14:05 ChiWPak

@ChiWPak Yes, please open a new issue. If you're familiar with Docker, it would help if you could supply a Dockerfile that produces the issue. I think you may be able to base it off of this: https://github.com/xeffyr/termux-docker

wch avatar May 08 '20 15:05 wch

Sorry for the late response. Thanks @wch, I'll start a new issue and try to figure out Docker.

ChiWPak avatar May 16 '20 22:05 ChiWPak