Skip to content

Initialize ICU when initializing Intl in order to catch data file issues early - #4984

Merged
chakrabot merged 2 commits into
chakra-core:masterfrom
jackhorton:icu/oom
Apr 13, 2018
Merged

Initialize ICU when initializing Intl in order to catch data file issues early#4984
chakrabot merged 2 commits into
chakra-core:masterfrom
jackhorton:icu/oom

Conversation

@jackhorton

@jackhorton jackhorton commented Apr 13, 2018

Copy link
Copy Markdown
Contributor

If ICU can't load the data file, it will report back U_FILE_ACCESS_ERROR or U_MISSING_RESOURCE_ERROR on calls to ICU APIs that require the data file. When using Windows ICU, the only reason we wouldn't be able to load the data file is if we are out of memory (with bundled ICU, the data should be statically or dynamically linked, and this shouldn't be an issue). As such, to reduce noise from ICU_ASSERT, we can load the data file as soon as we initialize Intl using u_init, and if that fails with a known error code, we can treat it as OOM.

@jefgen

jefgen commented Apr 13, 2018

Copy link
Copy Markdown
Collaborator

This might be okay as a temporary mitigation, but I would like to better understand the failures that are occurring.

@jackhorton

Copy link
Copy Markdown
Contributor Author

Sure. For what its worth, I also realized that I can probably check for this only in GetLocaleData and IsXLocaleAvailable, since those are the first functions that get called in the normal creation flow for Intl objects, and so if ICU is going to fail to load the data file, that's the only time it should happen.

@jefgen

jefgen commented Apr 13, 2018

Copy link
Copy Markdown
Collaborator

Just a thought, but can you perhaps call u_init() first, before calling any ICU functions?
This function should attempt to load the memory-mapped data file into memory, and you can check the status for errors to see if that is really the source of the issues.
API ref in case you are curious:
http://icu-project.org/apiref/icu4c/uclean_8h.html#ab6a4215b45b2162889aa1ff01e491d4c

@jackhorton

Copy link
Copy Markdown
Contributor Author

"u_init() will attempt to load some part of ICU's data … A successful invocation of u_init() does not, however, guarantee that all ICU data is accessible."

Any clarification on that? Why would it not be a guarantee?

@jefgen

jefgen commented Apr 13, 2018

Copy link
Copy Markdown
Collaborator

With ICU you can totally have some of the data broken out into separate ".res" files that might sit along side the "main" .dat file. This technique is used for some of the timezone related files, in order to more easily update them and service them.
Additionally, somebody might have decided to split up other parts of ICU into .res files for other components like code pages, etc.
There is no way that the API can guarantee that all of the data files will be loaded, it can only say that some of them would be. (Hopefully this makes sense?)

…ues early

If ICU can't load the data file, it will report back U_FILE_ACCESS_ERROR or U_MISSING_RESOURCE_ERROR on calls to ICU APIs that require the data file. When using Windows ICU, the only reason we wouldn't be able to load the data file is if we are out of memory (with bundled ICU, the data should be statically or dynamically linked, and this shouldn't be an issue). As such, to reduce noise from ICU_ASSERT, we can load the data file as soon as we initialize Intl using u_init, and if that fails with a known error code, we can treat it as OOM.
@jackhorton jackhorton changed the title Treat ICU OOMs as Chakra OOMs to help crawler better understand how to bucketize Initialize ICU when initializing Intl in order to catch data file issues early Apr 13, 2018
@jackhorton

Copy link
Copy Markdown
Contributor Author

@jefgen Updated to use u_init on initialization of Intl

@akroshg akroshg left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

:shipit:

@jefgen

jefgen commented Apr 13, 2018

Copy link
Copy Markdown
Collaborator

Thanks @jackhorton this LGTM.

Just to add a few notes, for future reference:
From stepping through the debugger and modifying the registers so as to lie about the return value from KERNELBASE!CreateFile2 , I am able reproduce having the status == "U_MISSING_RESOURCE_ERROR" when attempting to call ucol_getKeywordValuesForLocale().

ICU is theoretically supposed to be able to function without a data file at all, and with that in mind the error code U_MISSING_RESOURCE_ERROR isn’t exactly "wrong" per-se, though it is definitely not how I would think of things.

From stepping through the debugger and modifying the registers, I can confirm that if you do call the u_init() function and the data file fails to be mapped into memory then you will indeed get back U_FILE_ACCESS_ERROR -- which could be directly translated to OOM in the Chakra code.

In short, I think that perhaps some sort of ‘lazy-init’ call to the u_init() function before you make any ICU API calls might be the best approach for this issue.

if (status == U_MEMORY_ALLOCATION_ERROR || status == U_FILE_ACCESS_ERROR || status == U_MISSING_RESOURCE_ERROR)
{
// Trace that this happens in case there are build system changes that actually cause the data file to be not found
INTL_TRACE("Could not initialize ICU - u_init returned status %S", u_errorName(status));

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks for adding a trace here as well. It might be helpful in the future to know if the error code is File Access error or memory allocation error.

@jefgen jefgen left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM.

@jackhorton

Copy link
Copy Markdown
Contributor Author

@dotnet-bot test OSX static_osx_osx_release please
test OSX static_osx_osx_test please

@chakrabot
chakrabot merged commit 2149ac8 into chakra-core:master Apr 13, 2018
chakrabot pushed a commit that referenced this pull request Apr 13, 2018
…der to catch data file issues early

Merge pull request #4984 from jackhorton:icu/oom

If ICU can't load the data file, it will report back U_FILE_ACCESS_ERROR or U_MISSING_RESOURCE_ERROR on calls to ICU APIs that require the data file. When using Windows ICU, the only reason we wouldn't be able to load the data file is if we are out of memory (with bundled ICU, the data should be statically or dynamically linked, and this shouldn't be an issue). As such, to reduce noise from ICU_ASSERT, we can load the data file as soon as we initialize Intl using u_init, and if that fails with a known error code, we can treat it as OOM.
@dilijev

dilijev commented Apr 14, 2018

Copy link
Copy Markdown
Contributor

FWIW LGTM too

chakrabot pushed a commit that referenced this pull request Apr 22, 2018
…Kit ICU

Merge pull request #5011 from jackhorton:icu/init-windows-kit

Third attempt at this after #4984 and #5001, but I have actually confirmed that this makes Node-ChakraCore's chakracore-master branch build, launch, and run Intl code successfully once more. This definitely isn't the best solution, however if we refer to https://github.com/nodejs/node-chakracore/blob/d94b22785fb6ab7dde77cb13b7e95e958e581375/src/node_i18n.cc#L568-L581, we can see that Node somewhat explicitly also does not call u_init if they call udata_setCommonData.
@jackhorton
jackhorton deleted the icu/oom branch April 30, 2018 16:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants