Microsoft MVP성태의 닷넷 이야기
글쓴 사람
정성태 (seongtaejeong at gmail.com)
홈페이지
첨부 파일
 

(시리즈 글이 2개 있습니다.)
.NET Framework: 786. ASP.NET - HttpCookieCollection을 다중 스레드에서 사용할 경우 무한 루프 현상
; https://www.sysnet.pe.kr/2/0/11587

디버깅 기술: 221. WinDbg 분석 사례 - ASP.NET HttpCookieCollection을 다중 스레드에서 사용할 경우 무한 루프 현상 - 두 번째 이야기
; https://www.sysnet.pe.kr/2/0/13916




WinDbg 분석 사례 - ASP.NET HttpCookieCollection을 다중 스레드에서 사용할 경우 무한 루프 현상 - 두 번째 이야기

아래와 같이 덤프 파일을 분석해,

windbg 분석 사례 - x86 ASP.NET 웹 응용 프로그램의 CPU 100% 현상 (4)
; https://www.sysnet.pe.kr/2/0/13914

requestValidationMode 값을 4.0으로 설정하면 문제가 발생하지 않을 거라고 했는데, 그래도 여전히 해당 현상이 재현된다는 소식과 함께 다시 덤프 파일을 받았습니다.

이럴 땐 자연스럽게, ^^; 제 눈으로 본 것이 아니기 때문에 정말 4.0으로 설정했는지 확인해야 합니다. 어떻게 할 수 있을까요? ^^

우선 HttpRuntimeSection.RequestValidationMode 속성의 역어셈블 코드를 보면,

[ConfigurationProperty("requestValidationMode", DefaultValue = "4.0")]
[TypeConverter(typeof(VersionConverter))]
public Version RequestValidationMode
{
    get
    {
        if (this._requestValidationMode == null)
        {
            this._requestValidationMode = (Version)base[HttpRuntimeSection._propRequestValidationMode];
        }
        return this._requestValidationMode;
    }
    set
    {
        this._requestValidationMode = value;
        base[HttpRuntimeSection._propRequestValidationMode] = value;
    }
}

보는 바와 같이 _requestValidationMode 필드에 값이 보관됩니다. 다행히 HttpRuntimeSection은 Web Application에 1개의 인스턴스, 또는 다른 이유로 인해 1~2개 정도 더 생성될 것이라고 짐작할 수 있으므로 GC Heap에 존재할 그 인스턴스를 검색해 보면 됩니다.

// 우선 해당 타입의 MethodTable을 알아내고,
0:000> !name2ee System.Web.dll!System.Web.Configuration.HttpRuntimeSection
Module:      19c1a4c4
Assembly:    System.Web.dll
Token:       020006fe
MethodTable: 1a7c4248
EEClass:     1b5966e0
Name:        System.Web.Configuration.HttpRuntimeSection

// GC Heap에서 HttpRuntimeSection 인스턴스를 검색
0:000> !dumpheap -mt 1a7c4248
 Address       MT     Size
0b6522c8 1a7c4248      112     
0b652438 1a7c4248      112     

Statistics:
      MT    Count    TotalSize Class Name
1a7c4248        2          224 System.Web.Configuration.HttpRuntimeSection
Total 2 objects
Fragmented blocks larger than 0.5 MB:
    Addr     Size      Followed by
0a862394    0.6MB         0a8f6234 System.Byte[]

보는 바와 같이 2개의 인스턴스가 있는데요, 각각을 덤프해 보면,

// 인스턴스 1개는 _requestValidationMode 필드가 비어 있고,

0:000> !do 0b6522c8
Name:        System.Web.Configuration.HttpRuntimeSection
MethodTable: 1a7c4248
EEClass:     1b5966e0
Size:        112(0x70) bytes
File:        C:\Windows\Microsoft.Net\assembly\GAC_32\System.Web\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Web.dll
Fields:
      MT    Field   Offset                 Type VT     Attr    Value Name
0663aa48  4000198       30       System.Boolean  1 instance        0 _bDataToWrite
...[생략]...
0663c9b0  4002e15       50         System.Int32  1 instance       -1 _RequestLengthDiskThresholdBytes
1a62e23c  4002e17       3c       System.Version  0 instance 00000000 _requestValidationMode
0663c9b0  4002e18       54         System.Int32  1 instance        0 _MaxUrlLength
...[생략]...

// 다른 인스턴스에는 4.0.-1.-1 값이 설정됨

0:000> !do 0b652438
Name:        System.Web.Configuration.HttpRuntimeSection
MethodTable: 1a7c4248
EEClass:     1b5966e0
Size:        112(0x70) bytes
File:        C:\Windows\Microsoft.Net\assembly\GAC_32\System.Web\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Web.dll
Fields:
      MT    Field   Offset                 Type VT     Attr    Value Name
0663aa48  4000198       30       System.Boolean  1 instance        0 _bDataToWrite
...[생략]...
0663c9b0  4002e15       50         System.Int32  1 instance    81920 _RequestLengthDiskThresholdBytes
1a62e23c  4002e17       3c       System.Version  0 instance 0b652664 _requestValidationMode
0663c9b0  4002e18       54         System.Int32  1 instance      260 _MaxUrlLength
...[생략]...

0:000> !do 0b652664
Name:        System.Version
MethodTable: 1a62e23c
EEClass:     1a63b0c4
Size:        24(0x18) bytes
File:        C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
Fields:
      MT    Field   Offset                 Type VT     Attr    Value Name
0663c9b0  400073a        4         System.Int32  1 instance        4 _Major
0663c9b0  400073b        8         System.Int32  1 instance        0 _Minor
0663c9b0  400073c        c         System.Int32  1 instance       -1 _Build
0663c9b0  400073d       10         System.Int32  1 instance       -1 _Revision
19c14e2c  400073e      1d0        System.Char[]  0   shared   static SeparatorsArray

그러니까, requestValidationMode 값을 4.0으로 설정한 것이 맞고, 그럼에도 불구하고 문제가 발생하고 있는 것입니다.




그렇다면, 분명히 어떤 식으로든 EnableGranularValidation 코드가 수행되고 있다는 건데요, 이건 어떻게 확인할 수 있을까요? ^^

이를 위해 WinDbg를 동원할 필요는 없고, 위의 분석 대상이었던 응용 프로그램의 유형이 ASP.NET MVC 프로젝트였으므로 이에 대한 간단한 예제 프로젝트를 Visual Studio에서 생성한 후 쿠키를 사용하는 코드를 넣어,

public class HomeController : Controller
{
    public ActionResult Index()
    {
        var oldCookie = this.Request.Cookies["test"];
        this.Response.Cookies.Add(new HttpCookie("test", "testValue") { Expires = DateTime.Now.AddDays(1) });

        return View();
    }

    // ...[생략]...
}

디버깅을 시작해 솔루션 탐색기의 "External Sources"로부터 HttpCookieCollection 소스 코드를 열어 BP를 걸어보면 됩니다.

cookie_validation_on_mvc_1.png

실제로, web.config의 requestValidationMode를 4.0으로 설정해도,

<httpRuntime targetFramework="4.8" requestValidationMode="4.0" />

동일하게 BP가 걸리는데요, 이때의 callstack을 따라가 보면,

>    System.Web.dll!System.Web.HttpCookieCollection.EnableGranularValidation(System.Web.ValidateStringCallback validationCallback = {Method = Inspecting the state of an object in the debuggee of type System.Delegate is not supported in this context.}) Line 127 C#  Symbols loaded.
    System.Web.dll!System.Web.HttpRequest.Cookies.get() Line 1225   C#  Symbols loaded.
    net48_mvc.dll!net48_mvc.Controllers.HomeController.Index() Line 14  C#  Symbols loaded.
    [Lightweight Function]      Annotated Frame
    System.Web.Mvc.dll!System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(System.Web.Mvc.ControllerContext controllerContext = {System.Web.Mvc.ControllerContext}, System.Web.Mvc.ActionDescriptor actionDescriptor = {System.Web.Mvc.ReflectedActionDescriptor}, System.Collections.Generic.IDictionary<string, object> parameters) Line 253  C#  Symbols loaded.
    System.Web.Mvc.dll!System.Web.Mvc.Async.AsyncControllerActionInvoker.BeginInvokeSynchronousActionMethod.AnonymousMethod__9_0(System.IAsyncResult asyncResult, System.Web.Mvc.Async.AsyncControllerActionInvoker.ActionInvocation innerInvokeState) Line 304 C#  Symbols loaded.
    System.Web.Mvc.dll!System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult<System.__Canon, System.Web.Mvc.Async.AsyncControllerActionInvoker.ActionInvocation>.CallEndDelegate(System.IAsyncResult asyncResult) Line 224   C#  Symbols loaded.
    // ...[생략]...
    System.Web.dll!System.Web.Hosting.PipelineRuntime.ProcessRequestNotification(System.IntPtr rootedObjectsPointer, System.IntPtr nativeRequestContext, System.IntPtr moduleData, int flags) Line 386  C#  Symbols loaded.
    [AppDomain Transition]      Annotated Frame

관련 코드의 역어셈블 결과에서,

// HttpRequest.cs

public HttpCookieCollection Cookies
{
    get
    {
        EnsureCookies();
        if (_flags[4])
        {
            _flags.Clear(4);
            ValidateCookieCollection(_cookies);
        }
        return _cookies;
    }
}

private void ValidateCookieCollection(HttpCookieCollection cc)
{
	if (GranularValidationEnabled)
	{
		cc.EnableGranularValidation(delegate(string key, string value)
        {
            ValidateString(value, key, RequestValidationSource.Cookies);
        });
		return;
	}
	int count = cc.Count;
	for (int i = 0; i < count; i++)
	{
		string key2 = cc.GetKey(i);
		string value2 = cc.Get(i).Value;
		if (!string.IsNullOrEmpty(value2))
		{
			ValidateString(value2, key2, RequestValidationSource.Cookies);
		}
	}
}

Cookies get 메서드로부터 결국 _flags[4] 값으로 인해 EnableGranularValidation이 호출되고 있음을 알 수 있습니다. 그리고 다시, 그것은 GranularValidationEnabled get 속성이 true를 반환하기 때문인데,

// HttpRequest.cs

private const int granularValidationEnabled = 1073741824; // 0x40000000

private bool GranularValidationEnabled => _flags[0x40000000]; // 0x40000000

internal void EnableGranularRequestValidation()
{
	_flags[0x40000000] = true;
}

따라서 EnableGranularRequestValidation 메서드가 호출된 적이 있다는 것이므로 이것도 BP를 걸어 확인하면, 호출 스택이 이렇게 나오고,

>    System.Web.dll!System.Web.HttpRequest.EnableGranularRequestValidation() Line 2672   C#  Symbols loaded.
    System.Web.Mvc.dll!System.Web.Mvc.MvcHandler.ProcessRequestInit(System.Web.HttpContextBase httpContext = {System.Web.HttpContextWrapper}, out System.Web.Mvc.IController controller = null, out System.Web.Mvc.IControllerFactory factory = null) Line 168  C#  Symbols loaded.
    System.Web.Mvc.dll!System.Web.Mvc.MvcHandler.BeginProcessRequest(System.Web.HttpContextBase httpContext, System.AsyncCallback callback = {Method = {System.Reflection.RuntimeMethodInfo}}, object state = null) Line 86 C#  Symbols loaded.
    System.Web.dll!System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() Line 648 C#  Symbols loaded.
    System.Web.dll!System.Web.HttpApplication.ExecuteStepImpl(System.Web.HttpApplication.IExecutionStep step) Line 3596 C#  Symbols loaded.
    System.Web.dll!System.Web.HttpApplication.ExecuteStep(System.Web.HttpApplication.IExecutionStep step = {System.Web.HttpApplication.CallHandlerExecutionStep}, ref bool completedSynchronously = false) Line 3622    C#  Symbols loaded.
    System.Web.dll!System.Web.HttpApplication.PipelineStepManager.ResumeSteps(System.Exception error) Line 1161 C#  Symbols loaded.
    System.Web.dll!System.Web.HttpApplication.BeginProcessRequestNotification(System.Web.HttpContext context, System.AsyncCallback cb) Line 4054    C#  Symbols loaded.
    System.Web.dll!System.Web.HttpRuntime.ProcessRequestNotificationPrivate(System.Web.Hosting.IIS7WorkerRequest wr = {System.Web.Hosting.IIS7WorkerRequest}, System.Web.HttpContext context = {System.Web.HttpContext}) Line 1407  C#  Symbols loaded.
    System.Web.dll!System.Web.Hosting.PipelineRuntime.ProcessRequestNotificationHelper(System.IntPtr rootedObjectsPointer, System.IntPtr nativeRequestContext = 0x0000026e78687998, System.IntPtr moduleData, int flags) Line 461   C#  Symbols loaded.
    System.Web.dll!System.Web.Hosting.PipelineRuntime.ProcessRequestNotification(System.IntPtr rootedObjectsPointer, System.IntPtr nativeRequestContext, System.IntPtr moduleData, int flags) Line 386  C#  Symbols loaded.
    [Native to Managed Transition]      Annotated Frame
    [Managed to Native Transition]      Annotated Frame
    System.Web.dll!System.Web.Hosting.PipelineRuntime.ProcessRequestNotificationHelper(System.IntPtr rootedObjectsPointer, System.IntPtr nativeRequestContext, System.IntPtr moduleData, int flags) Line 499    C#  Symbols loaded.
    System.Web.dll!System.Web.Hosting.PipelineRuntime.ProcessRequestNotification(System.IntPtr rootedObjectsPointer, System.IntPtr nativeRequestContext, System.IntPtr moduleData, int flags) Line 386  C#  Symbols loaded.
    [AppDomain Transition]      Annotated Frame

Mvc 프레임워크에 놓인 ProcessRequestInit 메서드에서 ValidationUtility.EnableDynamicValidation 메서드를 호출하며, 그 원인은 다시 ValidationUtility.IsValidationEnabled가 true를 반환하기 때문입니다.


// MvcHandler.cs (System.Web.Mvc.dll)
private void ProcessRequestInit(HttpContextBase httpContext, out IController controller, out IControllerFactory factory)
{
    HttpContext current = HttpContext.Current;
    if (current != null && ValidationUtility.IsValidationEnabled(current) == true)
    {
        ValidationUtility.EnableDynamicValidation(current);
    }
    AddVersionHeader(httpContext);
    RemoveOptionalRoutingParameters();
    string requiredString = RequestContext.RouteData.GetRequiredString("controller");
    factory = ControllerBuilder.GetControllerFactory();
    controller = factory.CreateController(RequestContext, requiredString);
    if (controller == null)
    {
        throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, MvcResources.ControllerBuilder_FactoryReturnedNull, new object[2]
        {
            factory.GetType(),
            requiredString
        }));
    }
}

// Microsoft.Web.Infrastructure.dll

[EditorBrowsable(EditorBrowsableState.Never)]
public static class ValidationUtility
{
    // ...[생략]...

    [SecuritySafeCritical]
    public static bool? IsValidationEnabled(HttpContext context)
    {
        if (DynamicValidationShimReflectionUtil.Instance != null)
        {
            return DynamicValidationShimReflectionUtil.Instance.IsValidationEnabled(context);
        }
        return CollectionReplacer.IsValidationEnabled(context);
    }
}

// System.Web.dll

internal static class DynamicValidationShim
{
    internal static bool IsValidationEnabled(HttpContext context)
    {
        return context.Request.ValidateInputWasCalled;
    }

    // ...[생략]...
}

// HttpRequest.cs (System.Web.dll)

internal bool ValidateInputWasCalled => _flags[32768]; // 0x8000

public void ValidateInput()
{
    if (!ValidateInputWasCalled && !RequestValidationSuppressed)
    {
        _flags.Set(32768);
        _flags.Set(1);
        _flags.Set(2);
        _flags.Set(4);
        _flags.Set(64);
        _flags.Set(128);
        _flags.Set(256);
        _flags.Set(512);
        _flags.Set(8);
    }
}

끝이 보이는군요. ^^ 이제 ValidateInput이 호출된 위치를 다시 BP를 걸어 확인해 보면,

internal void ValidateInputIfRequiredByConfig()
{
    RuntimeConfig config = RuntimeConfig.GetConfig(Context);
    HttpRuntimeSection httpRuntime = config.HttpRuntime;
    if (CanValidateRequest())
    {
        string path = Path;
        if (path.Length > httpRuntime.MaxUrlLength)
        {
            throw new HttpException(400, SR.GetString("Url_too_long"));
        }
        if (QueryStringText.Length > httpRuntime.MaxQueryStringLength)
        {
            throw new HttpException(400, SR.GetString("QueryString_too_long"));
        }
        char[] requestPathInvalidCharactersArray = httpRuntime.RequestPathInvalidCharactersArray;
        if (requestPathInvalidCharactersArray != null && requestPathInvalidCharactersArray.Length != 0)
        {
            int num = path.IndexOfAny(requestPathInvalidCharactersArray);
            if (num >= 0)
            {
                string text = new string(path[num], 1);
                throw new HttpException(400, SR.GetString("Dangerous_input_detected", "Request.Path", text));
            }
            _flags.Set(65536);
        }
    }
    Version requestValidationMode = httpRuntime.RequestValidationMode;
    if (requestValidationMode == VersionUtil.Framework00)
    {
        _flags[int.MinValue] = true;
    }
    else if (requestValidationMode >= VersionUtil.Framework40)
    {
        ValidateInput();
        if (requestValidationMode >= VersionUtil.Framework45)
        {
            EnableGranularRequestValidation();
        }
    }
}

이렇게 requestValidationMode >= VersionUtil.Framework40인 상황에서 호출된 것이 MVC Framework에서는 (마이크로소프트가 의도한 것인지, 논리적으로 버그인 것인지 알 수 없으나) 기본적으로 Cookie의 EnableGranularValidation 기능을 활성화시켜버리는 것입니다.

결국, MVC 프로젝트라면 web.config에 requestValidationMode 값을 오히려 4.0 미만으로 설정해야 하는데, 가능한 값이 정해져 있으므로 2.0 정도로 내려야 합니다.




부가적으로 하나 더 정리하자면, ValidationUtility의 경우 중간에 DynamicValidationShimReflectionUtil.Instance를 접근하는데,

// ValidationUtility.cs (Microsoft.Web.Infrastructure.dll)

[SecuritySafeCritical]
public static bool? IsValidationEnabled(HttpContext context)
{
    if (DynamicValidationShimReflectionUtil.Instance != null)
    {
        return DynamicValidationShimReflectionUtil.Instance.IsValidationEnabled(context);
    }
    return CollectionReplacer.IsValidationEnabled(context);
}

이것은 Reflection을 이용해 System.Web.dll에 있는 Microsoft.Web.Infrastructure.DynamicValidationHelper.DynamicValidationShim 타입 정보를 로드하는 역할을 합니다.

// DynamicValidationShimReflectionUtil.cs (Microsoft.Web.Infrastructure.dll)

namespace Microsoft.Web.Infrastructure.DynamicValidationHelper;

[SecurityCritical]
internal sealed class DynamicValidationShimReflectionUtil
{
    // ...[생략]...

    [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "We catch and ignore all errors because we do not want to bring down the application.")]
    private static DynamicValidationShimReflectionUtil GetInstance()
    {
        try
        {
            DynamicValidationShimReflectionUtil dynamicValidationShimReflectionUtil = new DynamicValidationShimReflectionUtil();
            Type type = CommonAssemblies.SystemWeb.GetType("Microsoft.Web.Infrastructure.DynamicValidationHelper.DynamicValidationShim", throwOnError: false);
            if (type == null)
            {
                return null;
            }
            MethodInfo method = CommonReflectionUtil.FindMethod(type, "EnableDynamicValidation", isStatic: true, new Type[1] { typeof(HttpContext) }, typeof(void));
            dynamicValidationShimReflectionUtil.EnableDynamicValidation = CommonReflectionUtil.MakeDelegate<Action<HttpContext>>(method);
            CommonReflectionUtil.Assert(dynamicValidationShimReflectionUtil.EnableDynamicValidation != null);
            MethodInfo method2 = CommonReflectionUtil.FindMethod(type, "IsValidationEnabled", isStatic: true, new Type[1] { typeof(HttpContext) }, typeof(bool));
            dynamicValidationShimReflectionUtil.IsValidationEnabled = CommonReflectionUtil.MakeDelegate<Func<HttpContext, bool>>(method2);
            CommonReflectionUtil.Assert(dynamicValidationShimReflectionUtil.IsValidationEnabled != null);
            MethodInfo method3 = CommonReflectionUtil.FindMethod(type, "GetUnvalidatedCollections", isStatic: true, new Type[3]
            {
                typeof(HttpContext),
                typeof(Func<NameValueCollection>).MakeByRefType(),
                typeof(Func<NameValueCollection>).MakeByRefType()
            }, typeof(void));
            dynamicValidationShimReflectionUtil.GetUnvalidatedCollections = CommonReflectionUtil.MakeDelegate<GetUnvalidatedCollectionsCallback>(method3);
            CommonReflectionUtil.Assert(dynamicValidationShimReflectionUtil.GetUnvalidatedCollections != null);
            return dynamicValidationShimReflectionUtil;
        }
        catch
        {
            return null;
        }
    }
}

그리고 System.Web.dll에 있는 DynamicValidationShim은 마치 "Microsoft.Web.Infrastructure.dll"에서 접근할 수 있는 통로를 열어두는 것처럼 구현돼 있습니다.

// DynamicValidationShim.cs (System.Web.dll)
using System;
using System.Collections.Specialized;
using System.Web;

namespace Microsoft.Web.Infrastructure.DynamicValidationHelper;

internal static class DynamicValidationShim
{
    internal static void EnableDynamicValidation(HttpContext context)
    {
        context.Request.EnableGranularRequestValidation();
    }

    internal static bool IsValidationEnabled(HttpContext context)
    {
        return context.Request.ValidateInputWasCalled;
    }

    internal static void GetUnvalidatedCollections(HttpContext context, out Func<NameValueCollection> formGetter, out Func<NameValueCollection> queryStringGetter)
    {
        UnvalidatedRequestValues unvalidated = context.Request.Unvalidated;
        formGetter = () => unvalidated.Form;
        queryStringGetter = () => unvalidated.QueryString;
    }
}

사실 Microsoft.Web.Infrastructure.dll은 System.Web.dll을 직접 참조하고 있으므로 저런 식으로 접근할 필요가 없습니다. 그런데도, 이렇게 구현된 것은...? 아마도 닷넷 프레임워크의 BCL에 기본 포함된 System.Web.dll과는 달리 Microsoft.Web.Infrastructure.dll의 경우 .NET Framework 버전에 의존적이지 않게 만들 목적이었지 않았을까 싶습니다. 일례로, .NET 3.5 버전의 System.Web.dll에는 DynamicValidationShim 타입이 없다는 식의 고려를 한 것이 아닐까...라고 추측해 봅니다. ^^




[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]







[최초 등록일: ]
[최종 수정일: 4/23/2025]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 




... 16  17  18  19  20  21  [22]  23  24  25  26  27  28  29  30  ...
NoWriterDateCnt.TitleFile(s)
13388정성태7/3/202311851오류 유형: 871. 윈도우 탐색기에서 열리지 않는 zip 파일 - The Compressed (zipped) Folder '[...].zip' is invalid. [1]파일 다운로드1
13387정성태6/28/202311095오류 유형: 870. _mysql - Commands out of sync; you can't run this command now
13386정성태6/27/202311793Linux: 61. docker - 원격 제어를 위한 TCP 바인딩 추가
13385정성태6/27/202311676Linux: 60. Linux - 외부에서의 접속을 허용하기 위한 TCP 포트 여는 방법
13384정성태6/26/202311149.NET Framework: 2131. C# - Source Generator로 해결하는 enum 박싱 문제파일 다운로드1
13383정성태6/26/202310949개발 환경 구성: 683. GPU 런타임을 사용하는 Colab 노트북 설정
13382정성태6/25/202310826.NET Framework: 2130. C# - Win32 API를 이용한 윈도우 계정 정보 (예: 마지막 로그온 시간)파일 다운로드1
13381정성태6/25/202311793오류 유형: 869. Fatal Python error: init_fs_encoding: failed to get the Python codec of the filesystem encoding
13380정성태6/24/202310220스크립트: 52. 파이썬 3.x에서의 동적 함수 추가
13379정성태6/23/202310685스크립트: 51. 파이썬 2.x에서의 동적 함수 추가
13378정성태6/22/202310884오류 유형: 868. docker - build 시 "CANCELED ..." 뜨는 문제
13377정성태6/22/202315910오류 유형: 867. 파이썬 mysqlclient 2.2.x 설치 시 "Specify MYSQLCLIENT_CFLAGS and MYSQLCLIENT_LDFLAGS env vars manually" 오류
13376정성태6/21/202311641.NET Framework: 2129. C# - Polly를 이용한 클라이언트 측의 요청 재시도파일 다운로드1
13375정성태6/20/202310678스크립트: 50. Transformers (신경망 언어모델 라이브러리) 강좌 - 2장 코드 실행 결과
13374정성태6/20/202310393오류 유형: 866. 파이썬 - <class 'AttributeError'> module 'flask.json' has no attribute 'JSONEncoder'
13373정성태6/19/202311786오류 유형: 865. 파이썬 - pymssql 설치 관련 오류 정리
13372정성태6/15/202310550개발 환경 구성: 682. SQL Server TLS 통신을 위해 사용되는 키 길이 확인 방법
13371정성태6/15/202311019개발 환경 구성: 681. openssl - 인증서 버전(V1 / V3)
13370정성태6/14/202311262개발 환경 구성: 680. C# - Ubuntu + Microsoft.Data.SqlClient + SQL Server 2008 R2 연결 방법 - TLS 1.2 지원
13369정성태6/13/202310571개발 환경 구성: 679. PyCharm(을 비롯해 JetBrains에 속한 여타) IDE에서 내부 Window들의 탭이 없어진 경우
13368정성태6/13/202311343개발 환경 구성: 678. openssl로 생성한 인증서를 SQL Server의 암호화 인증서로 설정하는 방법
13367정성태6/10/202312109오류 유형: 864. openssl로 만든 pfx 인증서를 Windows Server 2016 이하에서 등록 시 "The password you entered is incorrect" 오류 발생
13366정성태6/10/202311244.NET Framework: 2128. C# - 윈도우 시스템에서 지원하는 암호화 목록(Cipher Suites) 나열파일 다운로드1
13365정성태6/8/202310192오류 유형: 863. MODIFY FILE encountered operating system error 112(failed to retrieve text for this error. Reason: 15105)
13364정성태6/8/202312337.NET Framework: 2127. C# - Ubuntu + Microsoft.Data.SqlClient + SQL Server 2008 R2 연결 방법 [1]
13363정성태6/7/202312000스크립트: 49. 파이썬 - "Transformers (신경망 언어모델 라이브러리) 강좌" - 1장 2절 코드 실행 결과
... 16  17  18  19  20  21  [22]  23  24  25  26  27  28  29  30  ...