[GHC] #10046: Linker script patch in rts/Linker.c doesn't work for (non-C or non-en..) locales

#10046: Linker script patch in rts/Linker.c doesn't work for (non-C or non-en..) locales -------------------------------------+------------------------------------- Reporter: hgolden | Owner: simonmar Type: bug | Status: new Priority: normal | Milestone: 7.12.1 Component: Runtime | Version: 7.8.4 System | Operating System: Unknown/Multiple Keywords: linker | Type of failure: Incorrect result script | at runtime Architecture: | Blocked By: Unknown/Multiple | Related Tickets: 2615, 9237 Test Case: | Blocking: | Differential Revisions: | -------------------------------------+------------------------------------- Please see ticket:2615#comment:40 and replies. This error only occurs on systems where linker scripts are used. The linker script patch (as it has evolved) assumes that the error messages it will receive are in English. This would be true if the locale (LC_MESSAGES) is C or en (or one of the en variants). However, in other locales, the message will be in a different language. Unfortunately, the semantics of POSIX dlerror() specify that the error is returned as a pointer to a human-readable text string, rather than an error code. The string returned depends on the locale. The code could be made more robust by momentarily changing the locale (LC_MESSAGES) to C before calling dlerror() and reverting it to its previous value immediately after. This has been tested on a zh_CN.utf-8 (see ticket:2615#comment:42) and works. The only concern I have is in the case of multithreaded code that _might_ be affected if it is running while the locale is changed. I don't know enough to know if this is a real issue or not, nor do I know how to deal with it if necessary. Also see ticket:9237 for another corner case in the linker script code that should be dealt with at the same time. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/10046 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#10046: Linker script patch in rts/Linker.c doesn't work for (non-C or non-en..) locales -------------------------------------+------------------------------------- Reporter: hgolden | Owner: simonmar Type: bug | Status: new Priority: normal | Milestone: 7.12.1 Component: Runtime System | Version: 7.8.4 Resolution: | Keywords: linker Operating System: Unknown/Multiple | script Type of failure: Incorrect result | Architecture: at runtime | Unknown/Multiple Blocked By: | Test Case: Related Tickets: 2615, 9237 | Blocking: | Differential Revisions: -------------------------------------+------------------------------------- Comment (by rwbarton):
The only concern I have is in the case of multithreaded code that _might_ be affected if it is running while the locale is changed. I don't know enough to know if this is a real issue or not, nor do I know how to deal with it if necessary.
Yes, this is an issue with `setlocale`. POSIX has `uselocale` and related functions which allow setting the locale on a per-thread basis, though. `dlopen` can execute code from the shared library it loads (constructor functions), so as you say we should only modify the locale around the call to `dlerror`, which should be safe. Really the most correct thing to do would be to return both the localized error message and the `LC_MESSAGES=C` error message from `internal_dlopen`, and use the latter message to detect linker scripts, and present the former message to the user if we ultimately can't load the shared library. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/10046#comment:1 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#10046: Linker script patch in rts/Linker.c doesn't work for (non-C or non-en..) locales -------------------------------------+------------------------------------- Reporter: hgolden | Owner: simonmar Type: bug | Status: new Priority: normal | Milestone: 7.12.1 Component: Runtime System | Version: 7.8.4 (Linker) | Keywords: linker Resolution: | script Operating System: Unknown/Multiple | Architecture: Type of failure: Incorrect result | Unknown/Multiple at runtime | Test Case: Blocked By: | Blocking: Related Tickets: 2615, 9237 | Differential Revisions: -------------------------------------+------------------------------------- Changes (by ezyang): * component: Runtime System => Runtime System (Linker) -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/10046#comment:2 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#10046: Linker script patch in rts/Linker.c doesn't work for (non-C or non-en..) locales -------------------------------------+------------------------------------- Reporter: hgolden | Owner: simonmar Type: bug | Status: new Priority: normal | Milestone: 7.12.1 Component: Runtime System | Version: 7.8.4 (Linker) | Keywords: linker Resolution: | script Operating System: Unknown/Multiple | Architecture: Type of failure: Incorrect result | Unknown/Multiple at runtime | Test Case: Blocked By: | Blocking: Related Tickets: 2615, 9237 | Differential Revisions: -------------------------------------+------------------------------------- Description changed by ezyang: Old description:
Please see ticket:2615#comment:40 and replies.
This error only occurs on systems where linker scripts are used. The linker script patch (as it has evolved) assumes that the error messages it will receive are in English. This would be true if the locale (LC_MESSAGES) is C or en (or one of the en variants). However, in other locales, the message will be in a different language. Unfortunately, the semantics of POSIX dlerror() specify that the error is returned as a pointer to a human-readable text string, rather than an error code. The string returned depends on the locale.
The code could be made more robust by momentarily changing the locale (LC_MESSAGES) to C before calling dlerror() and reverting it to its previous value immediately after. This has been tested on a zh_CN.utf-8 (see ticket:2615#comment:42) and works. The only concern I have is in the case of multithreaded code that _might_ be affected if it is running while the locale is changed. I don't know enough to know if this is a real issue or not, nor do I know how to deal with it if necessary.
Also see ticket:9237 for another corner case in the linker script code that should be dealt with at the same time.
New description: Please see ticket:2615#comment:40 and replies. A bug is illustrated by this Haskell program: {{{ import ObjLink import Foreign import Foreign.C.Types import Foreign.C.String foreign import ccall "setlocale" c_setlocale :: CInt -> CString -> IO CString main = do withCString "zh_CN.UTF-8" $ \lc -> c_setlocale 5 lc r <- loadDLL "/usr/lib/libc.so" putStrLn (show r) }}} which outputs: {{{ Just "/usr/lib/libc.so: \26080\25928\30340 ELF \22836" }}} The "\26080\25928\30340 ELF \22836" part is "无效的ELF头" in Chinese. This error only occurs on systems where linker scripts are used. The linker script patch (as it has evolved) assumes that the error messages it will receive are in English. This would be true if the locale (LC_MESSAGES) is C or en (or one of the en variants). However, in other locales, the message will be in a different language. Unfortunately, the semantics of POSIX dlerror() specify that the error is returned as a pointer to a human-readable text string, rather than an error code. The string returned depends on the locale. The code could be made more robust by momentarily changing the locale (LC_MESSAGES) to C before calling dlerror() and reverting it to its previous value immediately after. This has been tested on a zh_CN.utf-8 (see ticket:2615#comment:42) and works. The only concern I have is in the case of multithreaded code that _might_ be affected if it is running while the locale is changed. I don't know enough to know if this is a real issue or not, nor do I know how to deal with it if necessary. Also see ticket:9237 for another corner case in the linker script code that should be dealt with at the same time. -- -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/10046#comment:3 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#10046: Linker script patch in rts/Linker.c doesn't work for (non-C or non-en..) locales -------------------------------------+------------------------------------- Reporter: hgolden | Owner: simonmar Type: bug | Status: new Priority: normal | Milestone: 7.12.1 Component: Runtime System | Version: 7.8.4 (Linker) | Keywords: linker Resolution: | script Operating System: Unknown/Multiple | Architecture: Type of failure: Incorrect result | Unknown/Multiple at runtime | Test Case: Blocked By: | Blocking: Related Tickets: 2615, 9237 | Differential Revisions: -------------------------------------+------------------------------------- Comment (by ezyang): hgolden, I actually am having difficulty running your script and reproducing the same output. There are two problems. First, the path that is in your example doesn't exist on my system. There are a few possible candidates: `/usr/lib/x86_64-linux-gnu/libc.so` is a linker script that has contents {{{ /* GNU ld script Use the shared library, but some functions are only in the static library, so try that secondarily. */ OUTPUT_FORMAT(elf64-x86-64) GROUP ( /lib/x86_64-linux-gnu/libc.so.6 /usr/lib/x86_64-linux- gnu/libc_nonshared.a AS_NEEDED ( /lib/x86_64-linux-gnu/ld- linux-x86-64.so.2 ) ) }}} Then, when I run the script compiled by GHC 7.6.3, I get `Nothing`. So I can't seem to coax out the Chinese output. BTW, in GHC 7.10 you need to initialize the object linker, otherwise it will segfault. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/10046#comment:4 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#10046: Linker script patch in rts/Linker.c doesn't work for (non-C or non-en..) locales -------------------------------------+------------------------------------- Reporter: hgolden | Owner: simonmar Type: bug | Status: new Priority: normal | Milestone: 8.0.1 Component: Runtime System | Version: 7.8.4 (Linker) | Resolution: | Keywords: linker script Operating System: Unknown/Multiple | Architecture: Type of failure: Incorrect result | Unknown/Multiple at runtime | Test Case: Blocked By: | Blocking: Related Tickets: 2615, 9237 | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by trommler): * cc: trommler (added) -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/10046#comment:6 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

hgolden, I actually am having difficulty running your script and reproducing the same output. There are two problems. First, the path that is in your example doesn't exist on my system. There are a few possible candidates: `/usr/lib/x86_64-linux-gnu/libc.so` is a linker script that has contents
{{{ /* GNU ld script Use the shared library, but some functions are only in the static library, so try that secondarily. */ OUTPUT_FORMAT(elf64-x86-64) GROUP ( /lib/x86_64-linux-gnu/libc.so.6 /usr/lib/x86_64-linux- gnu/libc_nonshared.a AS_NEEDED ( /lib/x86_64-linux-gnu/ld-
#10046: Linker script patch in rts/Linker.c doesn't work for (non-C or non-en..) locales -------------------------------------+------------------------------------- Reporter: hgolden | Owner: simonmar Type: bug | Status: new Priority: normal | Milestone: 8.0.1 Component: Runtime System | Version: 7.8.4 (Linker) | Resolution: | Keywords: linker script Operating System: Unknown/Multiple | Architecture: Type of failure: Incorrect result | Unknown/Multiple at runtime | Test Case: Blocked By: | Blocking: Related Tickets: 2615, 9237 | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by hgolden): Replying to [comment:4 ezyang]: linux-x86-64.so.2 ) )
}}} My apology for not replying promptly! The library above should have the same results on your system. Please replace the library name in the `loadDLL` function with the name of any linker script on your test system. Then, when I run the script compiled by GHC 7.6.3, I get `Nothing`. So I can't seem to coax out the Chinese output. If you are getting `Nothing` that suggests a problem with the regular expression. It should find the `/lib/x86_64-linux-gnu/libc.so.6` in the GROUP command and try to `dlopen` it. I will investigate.
BTW, in GHC 7.10 you need to initialize the object linker, otherwise it will segfault. In the past the RTS initialized the object linker when it started up. Maybe this is related to a change in that logic?
-- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/10046#comment:7 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler
participants (1)
-
GHC