Skip to content

Commit 9e28eca

Browse files
committed
[GR-18163] setlocale() cleanup after fix in Prism and fix warnings
PullRequest: truffleruby/4232
2 parents 5de3856 + 2d79174 commit 9e28eca

File tree

7 files changed

+42
-17
lines changed

7 files changed

+42
-17
lines changed

mx.truffleruby/suite.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@
152152
"requires": ["java.management"],
153153
"dependencies": [
154154
"truffleruby:TRUFFLERUBY-ANNOTATIONS",
155+
"sdk:NATIVEIMAGE",
155156
"sdk:POLYGLOT",
156157
],
157158
"annotationProcessors": [
@@ -261,6 +262,9 @@
261262
"sulong:SULONG_API",
262263
"sulong:SULONG_NFI",
263264
"sdk:JLINE3",
265+
"sdk:COLLECTIONS",
266+
"sdk:NATIVEIMAGE",
267+
"sdk:POLYGLOT",
264268
# Library distributions, keep in sync with truffle_jars in mx_truffleruby.py
265269
"truffle:TRUFFLE_JCODINGS",
266270
"truffleruby:TRUFFLERUBY_JONI",
@@ -311,6 +315,7 @@
311315
"sdk:POLYGLOT",
312316
"sdk:LAUNCHER_COMMON",
313317
"sdk:MAVEN_DOWNLOADER",
318+
"sdk:NATIVEIMAGE",
314319
],
315320
"jacoco": "include",
316321
"javaCompliance": "17+",
@@ -489,6 +494,7 @@
489494
],
490495
"distDependencies": [
491496
"truffleruby:TRUFFLERUBY-ANNOTATIONS",
497+
"sdk:NATIVEIMAGE",
492498
"sdk:POLYGLOT",
493499
],
494500
"description": "TruffleRuby Shared constants and predicates",
@@ -531,6 +537,9 @@
531537
"sulong:SULONG_API",
532538
"sulong:SULONG_NFI",
533539
"sdk:JLINE3",
540+
"sdk:COLLECTIONS",
541+
"sdk:NATIVEIMAGE",
542+
"sdk:POLYGLOT",
534543
# Library distributions, keep in sync with truffle_jars in mx_truffleruby.py
535544
"truffle:TRUFFLE_JCODINGS",
536545
"truffleruby:TRUFFLERUBY_JONI",
@@ -600,6 +609,7 @@
600609
"sdk:POLYGLOT",
601610
"sdk:LAUNCHER_COMMON",
602611
"sdk:MAVEN_DOWNLOADER",
612+
"sdk:NATIVEIMAGE",
603613
],
604614
"description": "TruffleRuby Launcher",
605615
"license": ["EPL-2.0"],

src/main/java/org/truffleruby/RubyLanguage.java

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@
3939
import com.oracle.truffle.api.strings.AbstractTruffleString;
4040
import com.oracle.truffle.api.strings.InternalByteArray;
4141
import com.oracle.truffle.api.strings.TruffleString;
42+
import org.graalvm.nativeimage.ImageInfo;
43+
import org.graalvm.nativeimage.ProcessProperties;
4244
import org.graalvm.options.OptionDescriptors;
4345
import org.prism.Parser;
4446
import org.truffleruby.annotations.SuppressFBWarnings;
@@ -125,6 +127,7 @@
125127
import org.truffleruby.shared.Metrics;
126128
import org.truffleruby.shared.TruffleRuby;
127129
import org.truffleruby.shared.options.OptionsCatalog;
130+
import org.truffleruby.signal.LibRubySignal;
128131
import org.truffleruby.stdlib.CoverageManager;
129132

130133
import com.oracle.truffle.api.Assumption;
@@ -159,8 +162,7 @@
159162
RubyLanguage.MIME_TYPE_MAIN_SCRIPT },
160163
defaultMimeType = RubyLanguage.MIME_TYPE,
161164
dependentLanguages = { "nfi", "llvm", "regex" },
162-
fileTypeDetectors = RubyFileTypeDetector.class,
163-
needsAllEncodings = true)
165+
fileTypeDetectors = RubyFileTypeDetector.class)
164166
@ProvidedTags({
165167
CoverageManager.LineTag.class,
166168
TraceManager.CallTag.class,
@@ -459,6 +461,7 @@ public RubyContext createContext(Env env) {
459461
this.allocationReporter = env.lookup(AllocationReporter.class);
460462
this.options = new LanguageOptions(env, env.getOptions(), singleContext);
461463
setRubyHome(findRubyHome(env));
464+
setupLocale(env, rubyHome);
462465
loadLibYARPBindings();
463466
this.coreLoadPath = buildCoreLoadPath(this.options.CORE_LOAD_PATH);
464467
this.corePath = coreLoadPath + File.separator + "core" + File.separator;
@@ -540,6 +543,7 @@ protected boolean patchContext(RubyContext context, Env newEnv) {
540543

541544
synchronized (this) {
542545
setRubyHome(findRubyHome(newEnv));
546+
setupLocale(newEnv, rubyHome);
543547
loadLibYARPBindings();
544548
setupCleaner();
545549
}
@@ -820,6 +824,24 @@ private boolean isRubyHome(TruffleFile path) {
820824
lib.resolve("patches").isDirectory();
821825
}
822826

827+
private void setupLocale(Env env, String rubyHome) {
828+
// CRuby does setlocale(LC_CTYPE, "") because this is needed to get the locale encoding with nl_langinfo(CODESET).
829+
// This means every locale category except LC_CTYPE remains the initial "C".
830+
// LC_CTYPE is set according to environment variables (LC_ALL, LC_CTYPE, LANG).
831+
// HotSpot does setlocale(LC_ALL, "") and Native Image does nothing.
832+
// We match CRuby by doing setlocale(LC_ALL, "C") and setlocale(LC_CTYPE, "").
833+
// This also affects C functions that depend on the locale in C extensions, so best to follow CRuby here.
834+
// Change the strict minimum if embedded because setlocale() is process-wide.
835+
if (env.getOptions().get(OptionsCatalog.EMBEDDED_KEY)) {
836+
if (ImageInfo.inImageRuntimeCode()) {
837+
ProcessProperties.setLocale("LC_CTYPE", "");
838+
}
839+
} else {
840+
LibRubySignal.loadLibrary(rubyHome, Platform.LIB_SUFFIX);
841+
LibRubySignal.setupLocale();
842+
}
843+
}
844+
823845
private void loadLibYARPBindings() {
824846
String libyarpbindings = getRubyHome() + "/lib/libyarpbindings" + Platform.LIB_SUFFIX;
825847
Parser.loadLibrary(libyarpbindings);

src/main/java/org/truffleruby/core/DataObjectFinalizationService.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ public DataObjectFinalizationService(RubyLanguage language, ReferenceProcessor r
7171
this(language, referenceProcessor.processingQueue);
7272
}
7373

74+
@TruffleBoundary
7475
public DataObjectFinalizerReference addFinalizer(RubyContext context, Object object, Object finalizerCFunction,
7576
Object dataStruct) {
7677
final DataObjectFinalizerReference newRef = createRef(object, finalizerCFunction, dataStruct);

src/main/java/org/truffleruby/core/ReferenceProcessingService.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ public ReferenceProcessor(RubyContext context) {
7878
this.context = context;
7979
}
8080

81+
@TruffleBoundary
8182
void processReferenceQueue(ReferenceProcessingService<?, ?> service) {
8283
if (processOnMainThread()) {
8384
drainReferenceQueues();

src/main/java/org/truffleruby/core/encoding/EncodingManager.java

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,6 @@
3737

3838
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
3939
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
40-
import org.truffleruby.shared.Platform;
41-
import org.truffleruby.signal.LibRubySignal;
4240

4341
import static org.truffleruby.core.encoding.Encodings.INITIAL_NUMBER_OF_ENCODINGS;
4442

@@ -129,22 +127,12 @@ public void initializeDefaultEncodings(TruffleNFIPlatform nfi, NativeConfigurati
129127
}
130128

131129
private void initializeLocaleEncoding(TruffleNFIPlatform nfi, NativeConfiguration nativeConfiguration) {
132-
// CRuby does setlocale(LC_CTYPE, "") because this is needed to get the locale encoding with nl_langinfo(CODESET).
133-
// This means every locale category except LC_CTYPE remains the initial "C".
134-
// LC_CTYPE is set according to environment variables (LC_ALL, LC_CTYPE, LANG).
135-
// HotSpot does setlocale(LC_ALL, "") and Native Image does nothing.
136-
// We match CRuby by doing setlocale(LC_ALL, "C") and setlocale(LC_CTYPE, "").
137-
// This is notably important for Prism to be able to parse floating-point numbers:
138-
// https://github.com/ruby/prism/issues/2638
139-
// It also affects C functions that depend on the locale in C extensions, so best to follow CRuby here.
140-
LibRubySignal.loadLibrary(language.getRubyHome(), Platform.LIB_SUFFIX);
141-
LibRubySignal.setupLocale();
142-
143130
final String localeEncodingName;
144131
final String detector;
145132
if (nfi != null) {
146133
final int codeset = (int) nativeConfiguration.get("platform.langinfo.CODESET");
147134

135+
// nl_langinfo() needs setlocale(LC_CTYPE, "") before, which is done in RubyLanguage#setupLocale()
148136
// char *nl_langinfo(nl_item item);
149137
// nl_item is int on at least Linux and macOS
150138
final Object nl_langinfo = nfi.getFunction(context, "nl_langinfo", "(sint32):string");

src/main/java/org/truffleruby/language/backtrace/BacktraceFormatter.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ public static BacktraceFormatter createDefaultFormatter(RubyContext context, Rub
6969
// For debugging:
7070
// org.truffleruby.language.backtrace.BacktraceFormatter.printableRubyBacktrace(this)
7171
public static String printableRubyBacktrace(Object maybeNode) {
72-
final Node node = maybeNode instanceof Node ? (Node) maybeNode : null;
72+
final Node node = maybeNode instanceof Node n && n.isAdoptable() ? (Node) maybeNode : null;
7373
final RubyContext context = RubyLanguage.getCurrentContext();
7474
final BacktraceFormatter backtraceFormatter = new BacktraceFormatter(
7575
context,
@@ -79,7 +79,7 @@ public static String printableRubyBacktrace(Object maybeNode) {
7979
if (backtrace.isEmpty()) {
8080
return "<empty backtrace>";
8181
} else if (node == null) {
82-
return "# the first entry line is imprecise because 'this' is not a Node, select caller Java frames in the debugger until 'this' is a Node to fix this\n" +
82+
return "# the first entry line is imprecise because 'this' is not an adopted Node, select caller Java frames in the debugger until 'this' is an adopted Node to fix this\n" +
8383
backtrace;
8484
} else {
8585
return backtrace;

src/options.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ LANGUAGE_OPTIONS:
4848
- CLASS_CACHE
4949
- ARRAY_DUP_CACHE
5050
- ARRAY_STRATEGY_CACHE
51+
# Other
5152
- EXPERIMENTAL_ENGINE_CACHING
5253
- RUN_TWICE
5354
- CHECK_CLONE_UNINITIALIZED_CORRECTNESS
@@ -85,6 +86,8 @@ EXPERT:
8586
LAZY_RUBYGEMS: [lazy-rubygems, boolean, ['RUBYGEMS && ', DEFAULT_LAZY], Load RubyGems lazily on first failing require]
8687

8788
# Embedding options
89+
# It would be tempting to make these language options, but that does not work because the pre-initialized context is created with (isNativeAccessAllowed=false, embedded=true)
90+
# and it must be compatible (to be reused) with the runtime context created from the truffleruby launcher, which is (isNativeAccessAllowed=true, embedded=false).
8891
EMBEDDED: [embedded, boolean, true, 'Set default options for an embedded use of TruffleRuby, rather than top-level use']
8992
NATIVE_PLATFORM: [platform-native, boolean, ['env.isNativeAccessAllowed() && ', true], Enables native calls via Truffle NFI for internal functionality]
9093
NATIVE_INTERRUPT: [platform-native-interrupt, boolean, NATIVE_PLATFORM, Use the SIGVTALRM signal to interrupt native blocking calls]

0 commit comments

Comments
 (0)