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

with_language() fails to reset the cache on Alpine Linux #213

Closed
bastistician opened this issue Feb 15, 2023 · 8 comments · Fixed by #183
Closed

with_language() fails to reset the cache on Alpine Linux #213

bastistician opened this issue Feb 15, 2023 · 8 comments · Fixed by #183

Comments

@bastistician
Copy link

withr/R/language.R

Lines 48 to 50 in 35301f6

# resets the cache. So if there's some OS/setup that this technique fails
# on, we might try bindtextdomain() instead or as well.
local_locale(c(LC_MESSAGES = ""), .local_envir = .local_envir)

Yes there is: musl-based Alpine Linux.
example("with_language") gives:

wth_ln> with_language("en", try(mean[[1]]))
Error in mean[[1]] : object of type 'closure' is not subsettable

wth_ln> with_language("fr", try(mean[[1]]))
Error in mean[[1]] : objet de type 'closure' non indiçable

wth_ln> with_language("es", try(mean[[1]]))
Error in mean[[1]] : objet de type 'closure' non indiçable

All subsequent invocations of that error message stick to French.

R CMD checking withr fails for me from

expect_error(with_language("es", mean[[1]]), "no es subconjunto")

due to this issue.

In R >= 4.2.0, bindtextdomain(NULL) could be used to flush the cache, as in Sys.setLanguage(). This works on Alpine Linux:

> Sys.setLanguage("en"); try(mean[[1]])
Error in mean[[1]] : object of type 'closure' is not subsettable
> Sys.setLanguage("fr"); try(mean[[1]])
Error in mean[[1]] : objet de type 'closure' non indiçable
> Sys.setLanguage("es"); try(mean[[1]])
Error in mean[[1]] : objeto de tipo 'closure' no es subconjunto
sessionInfo()
R Under development (unstable) (2023-02-09 r83794)
Platform: x86_64-pc-linux-musl (64-bit)
Running under: Alpine Linux v3.17

Matrix products: default
BLAS:   /home/smeyer/QA/R-83794/build/lib/libRblas.so 
LAPACK: /home/smeyer/QA/R-83794/build/lib/libRlapack.so;  LAPACK version 3.11.0

locale:
[1] C.UTF-8 C       C       C       C       C      

time zone: Europe/Berlin
tzcode source: internal
@lionel-
Copy link
Member

lionel- commented Feb 15, 2023

cc @hadley

@maelle
Copy link

maelle commented Oct 9, 2023

@KevCaz noticed this bug in my post about potools

I observe the same behavior as @bastistician (on Ubuntu)

library("withr")
with_language("en", try(mean[[1]]))
#> Error in mean[[1]] : object of type 'closure' is not subsettable
with_language("fr", try(mean[[1]]))
#> Error in mean[[1]] : objet de type 'closure' non indiçable
with_language("es", try(mean[[1]]))
#> Error in mean[[1]] : objeto de tipo 'closure' no es subconjunto
try(mean[[1]])
#> Error in mean[[1]] : objeto de tipo 'closure' no es subconjunto

with_language("fr", try(mean[[1]]))
#> Error in mean[[1]] : objet de type 'closure' non indiçable
try(mean[[1]])
#> Error in mean[[1]] : objet de type 'closure' non indiçable

Created on 2023-10-09 with reprex v2.0.2

@lionel-
Copy link
Member

lionel- commented Oct 9, 2023

I had to also set LANG / LC_ALL in my unit tests: 08619ef. Does that fix it for you @maelle?

@hadley I wonder if we should try and set it automatically if not set already? We'd use some country as default for each language. To override, the user could supply a length-2 character vector. It might be tricky to have the mapping be both comprehensive and cross-platform.

@maelle
Copy link

maelle commented Oct 9, 2023

I had to change the locale code to make your example work on my machine but that seems to be expected for different OS. 😅

It seems to work!

with_lang <- function(lc, language, expr) {
  withr::local_envvar(c(LC_ALL = lc))
  withr::local_language(language)
  expr
}

with_lang("fr_FR.UTF-8", "fr", try(mean[[1]]))
#> Error in mean[[1]] : objet de type 'closure' non indiçable
try(mean[[1]])
#> Error in mean[[1]] : object of type 'closure' is not subsettable

Created on 2023-10-09 with reprex v2.0.2

@hadley
Copy link
Member

hadley commented Oct 9, 2023

@lionel- do we need to set LC_ALL to the matching language, or can we just set it to something other than C? Should we be using Sys.setLanguage() in versions of R that provide it?

@lionel-
Copy link
Member

lionel- commented Jan 9, 2024

After some reading including https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=931456 and https://bugs.r-project.org/show_bug.cgi?id=18055 here is my understanding of things:

  • LANGUAGE doesn't do anything when LC_ALL is set to C (see https://www.gnu.org/software/gettext/manual/html_node/The-LANGUAGE-variable.html) which is why I had to set LC_ALL in unit tests to override platforms where it is set to C (e.g. one of Kurt's Debian machines IIRC). This is an entirely separate problem.

  • There are cache invalidation bugs in GNU libc that require workarounds to force a reset. Setting LC_ALL / LANG envvars, like I did for the aforementioned issue, is one of them but should not be necessary here. We can use other workarounds, for instance the one Hadley experimented with in Try using bindtextdomain() for cache clearing #183, or the one Martin implemented in Sys.setLanguage() with bindtextdomain(NULL). For now I think I'd rather use Hadley's approach until we can drop support for R < 4.2.0, since Martin's workaround won't work on these older R versions.

@bastistician
Copy link
Author

Thanks! I can confirm that applying Commit a57401a (#183) on the current CRAN version 2.5.2 resolves the check failure for me: "Status: OK". 👍

@lionel-
Copy link
Member

lionel- commented Jan 9, 2024

Thanks for checking!

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 a pull request may close this issue.

4 participants