cefclient.exe crashes on Vista x64bit on newer processor supporting AVX instruction set

Issue #1410 resolved
Former user created an issue

Original issue 1410 created by elkhaze on 2014-10-17T21:25:21.000Z:

What steps will reproduce the problem?
1. Build the sample cefclient.exe (uses libcef.dll) for windows 64 bit

  1. Run it on Windows Vista x64 bit with Processor that support AVX instruction set. No crash when running on older processor that does not support AVX instruction set.

  2. Application will crash on startup as Vista does not support AVX. This issue does not happen on 32bit version of Vista. There is a guard on 32 bit, but not 64 bit.

What is the expected output? What do you see instead?
Crash, supplied client cefsample.exe crashes when run on Windows Vista X64 bit with a newer processor that support AVX. It will run fine on older processor that does not support AVX.

What version of the product are you using? On what operating system?
I am using cef_binary_3.1916.1839_windows64, same issue happens in cef_binary_3.2139.1840_windows64
On Windows Vista 64bit with newer processor supporting AVX.
This issue does not happen on older processors that do not support AVX instruction set.

Windows Vista x64 does not support AVX instruction set. Code doe Processor Guard, but should also do OS Guard.

Please provide any additional information below.
The libcef library using log function <math.h> to generate as part of the chromium library. This log function fails crashing the clientcef.exe as it tries to use the AVX instruction on a OS that does not support AVX (Vista x64)

Stack dump from cefclient.exe cef_binary_3.2139.1840_windows64_client
failed AVX instruction: vpsrlq xmm3,xmm0,34h

libcef.dll!log() Line 429 Asm
libcef.dll!tcmalloc::Sampler::Init(unsigned int seed) Line 92 + 0x86 bytes C++
libcef.dll!tcmalloc::ThreadCache::CreateCacheIfNecessary() Line 381 + 0x19 bytes C++
libcef.dll!`anonymous namespace'::do_malloc(unsigned __int64 size) Line 1097 + 0x5 bytes C++
libcef.dll!malloc(unsigned __int64 size) Line 111 C++
libcef.dll!calloc(unsigned __int64 n, unsigned __int64 elem_size) Line 109 + 0xd bytes C++
libcef.dll!_calloc_crt(unsigned __int64 count, unsigned __int64 size) Line 62 + 0xe bytes C
libcef.dll!_CRT_INIT(void * hDllHandle, unsigned long dwReason, void * lpreserved) Line 231 + 0xd bytes C
libcef.dll!__DllMainCRTStartup(void * hDllHandle, unsigned long dwReason, void * lpreserved) Line 371 + 0xd bytes C
ntdll.dll!0000000076fc0b47()
[Frames below may be incorrect and/or missing, no symbols loaded for ntdll.dll]
ntdll.dll!0000000076fa66df()
ntdll.dll!0000000076fa660e()

Comments (20)

  1. Marshall Greenblatt

    Comment 3. originally posted by magreenblatt on 2014-10-20T15:00:44.000Z:

    Since the problem reproduces with Chrome it's something that will need to be fixed in Chromium. Please file a bug at http://crbug.com.

  2. Former user Account Deleted

    Comment 4. originally posted by elkhaze on 2014-12-02T17:43:50.000Z:

    Here is a solution that I implemented in Libcef.dll which fixes the 64 bit crash on vista x64 with AVX instruction, I hope you add it in your code:

    in src\cef\libcef_dll\libcef_dll.cc

    #ifdef _WIN64
    #include <math.h>

    typedef decltype(&GetEnabledXStateFeatures) GetEnabledXStateFeatures_t;

    int __cdecl DisableAVX()
    {
    BOOL disableAVX = FALSE;

    // Operating system support check  
    if (!IsProcessorFeaturePresent(PF\_XSAVE\_ENABLED))  
    {  
        disableAVX = TRUE;  
    }   
    else   
    {  
         LPCWSTR strModuleName = L"kernel32.dll";  
        // extra check for AVX if the above API call returns TRUE  
        HMODULE kernel32Handle = GetModuleHandle(strModuleName);
    
        auto pGetEnabledXStateFeatures = (GetEnabledXStateFeatures\_t)GetProcAddress(  
            kernel32Handle, "GetEnabledXStateFeatures");  
        if (pGetEnabledXStateFeatures == NULL || (pGetEnabledXStateFeatures() & XSTATE\_MASK\_AVX) == 0)  
        {  
            disableAVX = TRUE;  
        }  
    }
    
    if (disableAVX)  
        \_set\_FMA3\_enable(0);  // this avoids any AVX instructions from being called in the CRT (e.g. from log() function)
    
    return 0;
    

    }

    class CDisableAVX {
    public:
    CDisableAVX() { DisableAVX(); }
    };

    CDisableAVX avx; // disable AVX based on platform
    #endif

  3. Former user Account Deleted

    Comment 5. originally posted by elkhaze on 2014-12-02T20:06:32.000Z:

    Also to view PDF documents on Vista X64 bit for systems that have AVX instructions, place same code in pdf DLL

    file: src\pdf\pdf.cc

  4. Marshall Greenblatt

    @Cardanine : The referenced links are all changes that CEF will pick up from Chromium automatically. Are you aware of any changes in chrome/ that require porting to CEF?

  5. Cardanine

    Apparently this was fixed in Chrome 41.0.2247.0, but it's still an issue with CEF 3.2272.2029 which uses Chrome 41.0.2272.43. I presume that CEF needs to call _set_FMA3_enable(0) as mentioned in comment 4 above.

  6. Joshua Chen

    same issue with CEF 3.2454.1342 on Windows 7 x64 (no SP1), but inside different call

    >   libcef.dll!log() Line 429   Unknown
        libcef.dll!base::Histogram::InitializeBucketRanges(int minimum, int maximum, base::BucketRanges * ranges=0x0000000003677580) Line 169   C++
        libcef.dll!base::Histogram::FactoryGet(const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & name={...}, int minimum=1, int maximum=10000, unsigned __int64 bucket_count=50, int flags=1) Line 100   C++
        libcef.dll!base::Histogram::FactoryGet(const char * name, int minimum=1, int maximum=10000, unsigned __int64 bucket_count=50, int flags=1) Line 139 C++
        libcef.dll!net::NetworkChangeNotifierWin::WatchForAddressChange() Line 279  C++
        libcef.dll!net::NetworkChangeNotifier::Create() Line 512    C++
        libcef.dll!content::BrowserMainLoop::PostMainMessageLoopStart() Line 539    C++
        libcef.dll!content::BrowserMainRunnerImpl::Initialize(const content::MainFunctionParams & parameters) Line 197  C++
        libcef.dll!`anonymous namespace'::CefUIThread::Init() Line 269  C++
        libcef.dll!base::Thread::ThreadMain() Line 242  C++
        libcef.dll!base::`anonymous namespace'::ThreadFunc(void * params=0x000000000064a360) Line 86    C++
        kernel32.dll!BaseThreadInitThunk() Unknown
        ntdll.dll!RtlUserThreadStart() Unknow
    
  7. Marshall Greenblatt

    If it's the same problem you should be able to resolve it in your client application by calling _set_FMA3_enable(0); before CefInitialize/CefExecuteProcess.

  8. Joshua Chen

    My project link against the official CEF dynamic libraries using VS2005, and the libcef.dll link against static VS2013 CRT libraries.

    While the _set_FMA3_enable(int) function is not exported, my linker can't find this symbol.

    Also, I think, even if I link against VS2013 CRT and call the _set_FMA3_enable(int), that only disables the AVX instructions for my static math library, right?

  9. Said Elkhazendar

    Hi Joshua Chen,

    You are correct. Unless Marshall agrees to incorporate the fix, you will need to re-build the library with the fix. This is what I have been doing since I posted the original issue & fix.

  10. Said Elkhazendar

    You can copy the same change form chrome_main.cc to src\cef\libcef_dll\libcef_dll.cc as the change needs to be a global variable at the entry point.

    #if defined(OS_WIN) && defined(ARCH_CPU_X86_64) // VS2013 only checks the existence of FMA3 instructions, not the enabled-ness // of them at the OS level (this is fixed in VS2015). We force off usage of // FMA3 instructions in the CRT to avoid using that path and hitting illegal // instructions when running on CPUs that support FMA3, but OSs that don't. // See http://crbug.com/436603. _set_FMA3_enable(0); #endif // WIN && ARCH_CPU_X86_64

  11. Log in to comment