none
Winscard. Number of handles climbing despite closing device context. Am I missing something? RRS feed

  • Question

  • Im trying to track down a memory leak in my app. The app should run 24/7 and monitors the status of an ACR38 smartcard reader for card inserts etc. I'm using Winscard, scard functions. Customers have reported exceptions about running out of handles.

    Windows 10 Enterprise V10.0.16299 build 16299, VS2017, C#

    I stripped down my code to a small winforms app that just calls the establish and release context functions on a 500ms timer.

    As the timer method is executed I can see total Handles in Task Manager keeps climbing and never drops. handle count remains static if I stop the timer.

    If I attempt to use the context after calling ReleaseContext, error code comes back as 0x00000006, so I assume that the context has been released.

    Does anybody know why please?

        [DllImport("Winscard.dll", EntryPoint = "SCardEstablishContext")]
        public static extern int SCardEstablishContext(
          uint dwScope,
          IntPtr nNotUsed1,
          IntPtr nNotUsed2,
          ref int phContext);
    
        [DllImport("Winscard.dll", EntryPoint = "SCardReleaseContext")]
        public static extern int SCardReleaseContext(int hContext);
    
        int errorCode = 0;
    
        private void timer1_Tick(object sender, EventArgs e)
        {
          var deviceContext = 0;
          errorCode = 0;
          bool result;
          try
          {
            result = EstablishContext(out deviceContext, out errorCode);
          }
          finally
          {
            if (deviceContext != 0)
              result = ReleaseContext(deviceContext, out errorCode);
          }
        }
    
        static bool EstablishContext(out int deviceContext, out int errCode)
        {
          const string fnName = "EstablishContext";
          deviceContext = 0;
          var j = IntPtr.Zero;
          var k = IntPtr.Zero;
          errCode = WinSCard.SCardEstablishContext(
            (int)WinSCard.
            SCardEstablisContextOptions.SCARD_SCOPE_USER,
            j,
            k,
            ref deviceContext);
          if (errCode != 0)
            LogDebug(fnName, "Failed to acquire context");
          return errCode == 0;
        }
    
        static bool ReleaseContext(int deviceContext, out int errCode)
        {
          errCode = 0;
          if (deviceContext != 0)
            errCode = WinSCard.SCardReleaseContext(deviceContext);
          return (errCode == 0);
        }// function



    Monday, March 12, 2018 3:40 PM

All replies

  • Have you checked the results of SCardReleaseContext?

    Note that the phContext parameter is defined as ULONG_PTR (in Windows API). Therefore using int is not always suitable. I think that you should use UIntPtr instead of int in several places.

    Tuesday, March 13, 2018 6:02 AM
  • Thanks for your input.

    I've changed the definition as you pointed out using uIntptr AND IntPtr. Originally I got that from pinvoke.net, but it's probably changed over the years.

    [DllImport("winscard.dll", EntryPoint = "SCardEstablishContext")]
        public static extern int SCardEstablishContext(
          uint dwScope,
          IntPtr nNotUsed1,
          IntPtr nNotUsed2,
          out UIntPtr phContext);

    This shows the same problem as before in both cases.
    I did find the following Microsoft reference to a recent patch, but it appears only to affect Windows 7 and Im running Windows 10. Should this be reported as a bug on Windows 10?

    https://support.microsoft.com/en-gb/help/4091290/march-1-2018-kb4091290

    "Summary


    This update addresses a known issue previously called out in KB4075211 where the LSM.EXE process and applications that call SCardEstablishContext or SCardReleaseContext may experience a handle leak. Once the leaked handle count reaches a certain threshold, smart card based operations fail with error with SCARD_E_NO_SERVICE"


    • Edited by Cheshirecat69 Tuesday, March 13, 2018 8:58 AM corrected
    Tuesday, March 13, 2018 8:53 AM
  • It could still be a bug. An easy way to check is to convert the code to C++ and then run the test again. If it still fails then it is likely an issue in Windows. 

    Also note that you should consider creating a wrapper SafeHandle type around the context information so you can simply use a using statement instead of the try-finally if this code is going to be heavily used.


    Michael Taylor http://www.michaeltaylorp3.net

    Wednesday, March 14, 2018 2:04 PM
    Moderator