Skip to content

Commit

Permalink
Bug #49, msvcrt模式_beginthread创建的线程无法获取ptd
Browse files Browse the repository at this point in the history
  • Loading branch information
mingkuang-Chuyu committed Jun 1, 2023
1 parent 9bc7bae commit d2dcef6
Show file tree
Hide file tree
Showing 7 changed files with 219 additions and 85 deletions.
10 changes: 5 additions & 5 deletions .github/workflows/Build&Test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -139,15 +139,15 @@ jobs:
$Env:PROCDUMP_PATH="$Env:GITHUB_WORKSPACE\Tools"
# 编译单元测试项目
&msbuild UnitTest\UnitTest.vcxproj "-p:Configuration=Dynamic;Platform=Win32;SolutionDir=$Env:GITHUB_WORKSPACE\\"
&msbuild UnitTest\UnitTest.vcxproj "-p:Configuration=Static;Platform=Win32;SolutionDir=$Env:GITHUB_WORKSPACE\\"
if($lastexitcode -ne 0)
{
throw "单元测试编译失败!退出代码:$lastexitcode"
}
$RunFaild = 0
&vstest.console Dynamic\UnitTest.dll "/logger:trx;LogFileName=UnitTest.trx" --Parallel "/Blame:CollectDump;CollectAlways=false;DumpType=full"
&vstest.console Static\UnitTest.dll "/logger:trx;LogFileName=UnitTest.trx" --Parallel "/Blame:CollectDump;CollectAlways=false;DumpType=full"
if($lastexitcode -ne 0)
{
$RunFaild = 1
Expand Down Expand Up @@ -217,9 +217,9 @@ jobs:
path: |
TestResults/**/*.dmp
TestResults/**/Sequence_*.xml
Dynamic\UnitTest.dll
Dynamic\UnitTest.pdb
Dynamic\*.log
Static\UnitTest.dll
Static\UnitTest.pdb
Static\*.log
UnitTest/SymbolBuildTest/.test/**/Build.log
*.7z
Expand Down
7 changes: 5 additions & 2 deletions Build.proj
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,16 @@
</Target>

<Import Project="$(VCInstallDir)\Auxiliary\Build\Microsoft.VCToolsVersion.default.props" />

<Target Name="Build">
<Target Name="DownloadTools" BeforeTargets="Build;PackRedist">
<!--下载LibMaker-->
<DownloadFile
Condition="!Exists('$(MSBuildThisFileDirectory)Tools\LibMaker.exe')"
SourceUrl="https://github.com/Chuyu-Team/LibMaker/releases/download/v1.0.2/LibMaker.exe"
DestinationFolder="$(MSBuildThisFileDirectory)Tools" DestinationFileName="LibMaker.exe"/>
</Target>

<Target Name="Build">

<!--提取所有需要编译的配置-->
<MSBuild Projects="%(ProjectReferenceWork.Identity)" StopOnFirstFailure="True" Properties="_GetProjectAllConfiguration=true;ForceImportAfterCppTargets=$(MSBuildThisFileFullPath)" Targets="_GetProjectAllConfiguration">
Expand Down
67 changes: 57 additions & 10 deletions Sources/ucrt/inc/corecrt_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -1489,23 +1489,70 @@ __declspec(dllimport) void __cdecl _amsg_exit(

__acrt_ptd* __cdecl __acrt_getptd_head(void);
#ifdef __BuildWithMSVCRT
__forceinline __acrt_ptd* __cdecl __acrt_getptd_noexit(void)
__declspec(noinline) __inline __acrt_ptd* __cdecl __acrt_getptd_noexit(void)
{
__acrt_ptd* ptd = (__acrt_ptd*)(((unsigned char*)_errno()) - FIELD_OFFSET(__acrt_ptd, _terrno));

/*
当 _thandle = -1,这表明此线程的ptd通过msvcrt.dll begin_thread 或者 __getptd_noexit 创建。
当 _thandle = 0,这表明此线程的ptd通过msvcrt.dll的DllMain创建。
当 _thandle = 其他,这表明msvcrt.dll内部内存已经申请失败。
*/
return (ptd->_thandle == (uintptr_t)-1/*Current Thread Handle*/ || ptd->_thandle == 0) ? ptd : (__acrt_ptd*)NULL;
// ptd->_thandle 一共有3中情况:
// 当 _thandle = -1,这表明此线程的ptd通过msvcrt.dll _beginthreadex 或者 __getptd_noexit 创建。
// 当 _thandle = 0,这表明此线程的ptd通过msvcrt.dll的DllMain创建。
// 当 _thandle = 其他,这可能是通过_beginthread启动的线程,它是实际有效的线程句柄。但是也有可能是内存申请失败了。

// 我们不要再根据 ptd->_thandle 判断__getptd_noexit 内存是否申请失,因为我们必须考虑 _beginthread 创建的线程。
// 这时必须借助GetThreadId,可是它开销是惊人的,不容易做到快速判断。
// 结合总总情况,我们现在通过判断 _errno() 返回地址是否在msvcrt模块范围来判断 __getptd_noexit 是否发生内存申请失败。
// 具体Bug请参考:https://github.com/Chuyu-Team/VC-LTL5/issues/49
typedef struct _DllAddressInfo
{
uintptr_t uBaseAddress;
uintptr_t uEndAddress;
} DllAddressInfo;

static DllAddressInfo s_DllAddressCache;

if (s_DllAddressCache.uBaseAddress == 0)
{
DllAddressInfo _DllAddressInfo = { (uintptr_t)-1, (uintptr_t)-1};
MEMORY_BASIC_INFORMATION _BaseInfo;
if (VirtualQuery(&_amsg_exit, &_BaseInfo, sizeof(_BaseInfo)))
{
_DllAddressInfo.uBaseAddress = (uintptr_t)_BaseInfo.AllocationBase;
_DllAddressInfo.uEndAddress = (uintptr_t)_BaseInfo.BaseAddress + _BaseInfo.RegionSize;

for (; VirtualQuery((void*)(_DllAddressInfo.uEndAddress + 1), &_BaseInfo, sizeof(_BaseInfo));)
{
if (_DllAddressInfo.uBaseAddress != (uintptr_t)_BaseInfo.AllocationBase)
break;

_DllAddressInfo.uEndAddress = (uintptr_t)_BaseInfo.BaseAddress + _BaseInfo.RegionSize;
}
}

#if defined(_X86_) || defined(_ARM_)
static_assert(sizeof(s_DllAddressCache) == sizeof(LONGLONG), "");
InterlockedCompareExchange64((volatile LONGLONG*)&s_DllAddressCache, *(LONGLONG*)&_DllAddressInfo, 0);
#elif defined(_IA64_) || defined(_AMD64_) || defined(_ARM64_)
// AMD 早期不支持 InterlockedCompareExchange128,所以不用……
InterlockedCompareExchange64((volatile LONGLONG*)&s_DllAddressCache.uEndAddress, _DllAddressInfo.uEndAddress, 0);
InterlockedCompareExchange64((volatile LONGLONG*)&s_DllAddressCache.uBaseAddress, _DllAddressInfo.uBaseAddress, 0);
#else
#error unsrpport!
#endif
}

uintptr_t _p_errno_value = (uintptr_t)_errno();
if (_p_errno_value == 0 || (s_DllAddressCache.uBaseAddress <= _p_errno_value && _p_errno_value < s_DllAddressCache.uEndAddress))
{
return NULL;
}

__acrt_ptd* ptd = (__acrt_ptd*)(((unsigned char*)_p_errno_value) - FIELD_OFFSET(__acrt_ptd, _terrno));
return ptd;
}
#else
__acrt_ptd* __cdecl __acrt_getptd_noexit(void);
#endif

#ifdef __BuildWithMSVCRT
__forceinline __acrt_ptd* __cdecl __acrt_getptd(void)
__declspec(noinline) __inline __acrt_ptd* __cdecl __acrt_getptd(void)
{
__acrt_ptd* ptd = __acrt_getptd_noexit();

Expand Down
71 changes: 39 additions & 32 deletions UnitTest/UnitTest.vcxproj
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="DDynamic|Win32">
<Configuration>DDynamic</Configuration>
<ProjectConfiguration Include="DStatic|Win32">
<Configuration>DStatic</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Dynamic|Win32">
<Configuration>Dynamic</Configuration>
<ProjectConfiguration Include="Static|Win32">
<Configuration>Static</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="DDynamic|x64">
<Configuration>DDynamic</Configuration>
<ProjectConfiguration Include="DStatic|x64">
<Configuration>DStatic</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Dynamic|x64">
<Configuration>Dynamic</Configuration>
<ProjectConfiguration Include="Static|x64">
<Configuration>Static</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
Expand All @@ -27,29 +27,31 @@
<ProjectSubType>NativeUnitTestProject</ProjectSubType>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DDynamic|Win32'" Label="Configuration">
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DStatic|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<UseOfMfc>false</UseOfMfc>
<WindowsTargetPlatformMinVersion>5.1.2600.0</WindowsTargetPlatformMinVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Dynamic|Win32'" Label="Configuration">
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Static|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<UseOfMfc>false</UseOfMfc>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DDynamic|x64'" Label="Configuration">
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DStatic|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<UseOfMfc>false</UseOfMfc>
<WindowsTargetPlatformMinVersion>5.1.2600.0</WindowsTargetPlatformMinVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Dynamic|x64'" Label="Configuration">
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Static|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
Expand All @@ -62,60 +64,62 @@
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='DDynamic|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='DStatic|Win32'">
<Import Project="..\VC-LTL helper for Visual Studio.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Dynamic|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Static|Win32'">
<Import Project="..\VC-LTL helper for Visual Studio.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='DDynamic|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='DStatic|x64'">
<Import Project="..\VC-LTL helper for Visual Studio.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Dynamic|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Static|x64'">
<Import Project="..\VC-LTL helper for Visual Studio.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DDynamic|Win32'">
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DStatic|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DDynamic|x64'">
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DStatic|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Dynamic|Win32'">
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Static|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Dynamic|x64'">
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Static|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DDynamic|Win32'">
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DStatic|Win32'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<AdditionalIncludeDirectories>$(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>SymbolBuildTestPath=LR"($(ProjectDir)SymbolBuildTest\)";MSBuildBinPath=LR"($(MSBuildBinPath)\)";VC_LTL_ROOT=LR"($(ProjectDir)..\)";VCToolsInstallDir=LR"($(VCToolsInstallDir))";CurrentUniversalCRTSdkDir=LR"($(UniversalCRTSdkDir)Lib\$(WindowsTargetPlatformVersion)\)";WIN32;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<UseFullPaths>true</UseFullPaths>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<AdditionalLibraryDirectories>$(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DDynamic|x64'">
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DStatic|x64'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<AdditionalIncludeDirectories>$(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>SymbolBuildTestPath=LR"($(ProjectDir)SymbolBuildTest\)";MSBuildBinPath=LR"($(MSBuildBinPath)\)";VC_LTL_ROOT=LR"($(ProjectDir)..\)";VCToolsInstallDir=LR"($(VCToolsInstallDir))";CurrentUniversalCRTSdkDir=LR"($(UniversalCRTSdkDir)Lib\$(WindowsTargetPlatformVersion)\)";_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<UseFullPaths>true</UseFullPaths>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<AdditionalLibraryDirectories>$(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Dynamic|Win32'">
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Static|Win32'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
Expand All @@ -125,6 +129,7 @@
<PreprocessorDefinitions>SymbolBuildTestPath=LR"($(ProjectDir)SymbolBuildTest\)";MSBuildBinPath=LR"($(MSBuildBinPath)\)";VC_LTL_ROOT=LR"($(ProjectDir)..\)";VCToolsInstallDir=LR"($(VCToolsInstallDir))";CurrentUniversalCRTSdkDir=LR"($(UniversalCRTSdkDir)Lib\$(WindowsTargetPlatformVersion)\)";WIN32;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<UseFullPaths>true</UseFullPaths>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
Expand All @@ -133,7 +138,7 @@
<AdditionalLibraryDirectories>$(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Dynamic|x64'">
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Static|x64'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
Expand All @@ -143,6 +148,7 @@
<PreprocessorDefinitions>SymbolBuildTestPath=LR"($(ProjectDir)SymbolBuildTest\)";MSBuildBinPath=LR"($(MSBuildBinPath)\)";VC_LTL_ROOT=LR"($(ProjectDir)..\)";VCToolsInstallDir=LR"($(VCToolsInstallDir))";CurrentUniversalCRTSdkDir=LR"($(UniversalCRTSdkDir)Lib\$(WindowsTargetPlatformVersion)\)";NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<UseFullPaths>true</UseFullPaths>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
Expand All @@ -154,11 +160,12 @@
<ItemGroup>
<ClCompile Include="detect_mismatch_UnitTest.cpp" />
<ClCompile Include="pch.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='DDynamic|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='DDynamic|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Dynamic|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Dynamic|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='DStatic|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='DStatic|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Static|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Static|x64'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="ptdTest.cpp" />
<ClCompile Include="RCBuildUnitTest.cpp" />
<ClCompile Include="UnitTest.cpp" />
</ItemGroup>
Expand Down
3 changes: 3 additions & 0 deletions UnitTest/UnitTest.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@
<ClCompile Include="RCBuildUnitTest.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="ptdTest.cpp">
<Filter>源文件</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="pch.h">
Expand Down
Loading

0 comments on commit d2dcef6

Please sign in to comment.