System.Data.SQLite
Check-in [320066944e]
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Add the 'PreLoadSQLite_BreakIntoDebugger' configuration setting to improve debugging support. Also, add some logging to the SQLiteProviderFactory class, pursuant to [d6e1fdba1e].
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 320066944e139af62e45d67e3c84608947652dbc
User & Date: mistachkin 2017-11-01 00:58:45
Context
2017-11-01
01:00
Adjust comment wording. check-in: b7307ff8d3 user: mistachkin tags: trunk
00:58
Add the 'PreLoadSQLite_BreakIntoDebugger' configuration setting to improve debugging support. Also, add some logging to the SQLiteProviderFactory class, pursuant to [d6e1fdba1e]. check-in: 320066944e user: mistachkin tags: trunk
2017-10-31
22:21
Improvements to the doc comments for the BackupDatabase method. check-in: e4df0a7df0 user: mistachkin tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to Doc/Extra/Provider/environment.html.

   192    192             <td>If this environment variable is set [to anything], it will be
   193    193             used instead of the application base directory by the native
   194    194             library pre-loader.  This environment variable can be especially
   195    195             useful in ASP.NET and other hosted environments where direct control
   196    196             of the location of the managed assemblies is not under the control
   197    197             of the application.</td>
   198    198           </tr>
          199  +        <tr valign="top">
          200  +          <td>PreLoadSQLite_BreakIntoDebugger</td>
          201  +          <td>If this configuration variable is set [to anything], the native
          202  +          library pre-loader subsystem will attempt to give the interactive
          203  +          user an opportunity to attach a debugger to the current process.</td>
          204  +        </tr>
   199    205           <tr valign="top">
   200    206             <td>PreLoadSQLite_LibraryFileNameOnly</td>
   201    207             <td>If this environment variable is set [to anything], it will be
   202    208             used as the base file name (without directory information) for the
   203    209             native SQLite library to be pre-loaded (e.g. "sqlite3.dll" or
   204    210             "libsqlite3.so.0").</td>
   205    211           </tr>

Changes to System.Data.SQLite.Linq/SQLiteProviderFactory.cs.

     9      9   namespace System.Data.SQLite.EF6
    10     10   #else
    11     11   namespace System.Data.SQLite.Linq
    12     12   #endif
    13     13   {
    14     14       using System;
    15     15       using System.Data.Common;
           16  +    using System.Globalization;
    16     17   
    17     18   #if USE_ENTITY_FRAMEWORK_6
    18     19       using System.Data.Entity.Core.Common;
    19     20   #endif
    20     21   
    21     22       /// <summary>
    22     23       /// SQLite implementation of <see cref="DbProviderFactory" />.
................................................................................
   136    137           public object GetService(
   137    138               Type serviceType
   138    139               )
   139    140           {
   140    141               if ((serviceType == typeof(ISQLiteSchemaExtensions)) ||
   141    142                   (serviceType == typeof(DbProviderServices)))
   142    143               {
          144  +                SQLiteLog.LogMessage(HelperMethods.StringFormat(
          145  +                    CultureInfo.CurrentCulture,
          146  +                    "IServiceProvider.GetService for type \"{0}\" (success).",
          147  +                    serviceType));
          148  +
   143    149                   return SQLiteProviderServices.Instance;
   144    150               }
          151  +
          152  +            SQLiteLog.LogMessage(HelperMethods.StringFormat(
          153  +                CultureInfo.CurrentCulture,
          154  +                "IServiceProvider.GetService for type \"{0}\" (failure).",
          155  +                serviceType));
   145    156   
   146    157               return null;
   147    158           }
   148    159           #endregion
   149    160   
   150    161           ///////////////////////////////////////////////////////////////////////
   151    162   

Changes to System.Data.SQLite/Configurations/System.Data.SQLite.dll.config.

   152    152                 useful in ASP.NET and other hosted environments where direct
   153    153                 control of the location of the managed assemblies is not under
   154    154                 the control of the application.
   155    155       -->
   156    156       <!--
   157    157       <add key="PreLoadSQLite_BaseDirectory" value="" />
   158    158       -->
          159  +
          160  +    <!--
          161  +        NOTE: If this configuration variable is set [to anything], the native
          162  +              library pre-loader subsystem will attempt to give the interactive
          163  +              user an opportunity to attach a debugger to the current process.
          164  +    -->
          165  +    <!--
          166  +    <add key="PreLoadSQLite_BreakIntoDebugger" value="1" />
          167  +    -->
   159    168   
   160    169       <!--
   161    170           NOTE: If this configuration variable is set [to anything], it will be
   162    171                 used as the base file name (without directory information) for
   163    172                 the native SQLite library to be pre-loaded (e.g. "sqlite3.dll"
   164    173                 or "libsqlite3.so.0").
   165    174       -->

Changes to System.Data.SQLite/UnsafeNativeMethods.cs.

     6      6    ********************************************************/
     7      7   
     8      8   namespace System.Data.SQLite
     9      9   {
    10     10     using System;
    11     11     using System.Globalization;
    12     12   
    13         -#if !NET_COMPACT_20 && (TRACE_DETECTION || TRACE_SHARED || TRACE_PRELOAD || TRACE_HANDLE)
           13  +#if TRACE_DETECTION || TRACE_SHARED || TRACE_PRELOAD || TRACE_HANDLE
    14     14     using System.Diagnostics;
    15     15   #endif
    16     16   
    17     17     using System.Collections.Generic;
    18     18     using System.IO;
    19     19     using System.Reflection;
    20     20   
................................................................................
   268    268         /////////////////////////////////////////////////////////////////////////
   269    269         /// <summary>
   270    270         /// Keeps track of whether we are running on Mono.  Initially null, it is
   271    271         /// set by the <see cref="IsMono" /> method on its first call.  Later, it
   272    272         /// is returned verbatim by the <see cref="IsMono" /> method.
   273    273         /// </summary>
   274    274         private static bool? isMono = null;
          275  +
          276  +      /////////////////////////////////////////////////////////////////////////
          277  +      /// <summary>
          278  +      /// Keeps track of whether we successfully invoked the
          279  +      /// <see cref="Debugger.Break" /> method.  Initially null, it is set by
          280  +      /// the <see cref="MaybeBreakIntoDebugger" /> method on its first call.
          281  +      /// </summary>
          282  +      private static bool? debuggerBreak = null;
   275    283         #endregion
   276    284   
   277    285         /////////////////////////////////////////////////////////////////////////
   278    286   
   279    287         #region Private Methods
          288  +      /// <summary>
          289  +      /// Determines the ID of the current process.  Only used for debugging.
          290  +      /// </summary>
          291  +      /// <returns>
          292  +      /// The ID of the current process -OR- zero if it cannot be determined.
          293  +      /// </returns>
          294  +      private static int GetProcessId()
          295  +      {
          296  +          Process process = Process.GetCurrentProcess();
          297  +
          298  +          if (process == null)
          299  +              return 0;
          300  +
          301  +          return process.Id;
          302  +      }
          303  +
          304  +      ///////////////////////////////////////////////////////////////////////
          305  +
   280    306         /// <summary>
   281    307         /// Determines whether or not this assembly is running on Mono.
   282    308         /// </summary>
   283    309         /// <returns>
   284    310         /// Non-zero if this assembly is running on Mono.
   285    311         /// </returns>
   286    312         private static bool IsMono()
................................................................................
   303    329             return false;
   304    330         }
   305    331         #endregion
   306    332   
   307    333         /////////////////////////////////////////////////////////////////////////
   308    334   
   309    335         #region Internal Methods
          336  +      /// <summary>
          337  +      /// If the "PreLoadSQLite_BreakIntoDebugger" configuration setting is
          338  +      /// present (e.g. via the environment), give the interactive user the
          339  +      /// opportunity to attach a debugger to the current process; otherwise,
          340  +      /// do nothing.
          341  +      /// </summary>
          342  +      private static void MaybeBreakIntoDebugger()
          343  +      {
          344  +          lock (staticSyncRoot)
          345  +          {
          346  +              if (debuggerBreak != null)
          347  +                  return;
          348  +          }
          349  +
          350  +          if (UnsafeNativeMethods.GetSettingValue(
          351  +                "PreLoadSQLite_BreakIntoDebugger", null) != null)
          352  +          {
          353  +              //
          354  +              // NOTE: Attempt to use the Console in order to prompt the
          355  +              //       interactive user (if any).  This may fail for any
          356  +              //       number of reasons.  Even in those cases, we still
          357  +              //       want to issue the actual request to break into the
          358  +              //       debugger.
          359  +              //
          360  +              try
          361  +              {
          362  +                  Console.WriteLine(StringFormat(
          363  +                      CultureInfo.CurrentCulture,
          364  +                      "Attach a debugger to process {0} " +
          365  +                      "and press any key to continue.",
          366  +                      GetProcessId()));
          367  +
          368  +#if PLATFORM_COMPACTFRAMEWORK
          369  +                  Console.ReadLine();
          370  +#else
          371  +                  Console.ReadKey();
          372  +#endif
          373  +              }
          374  +#if !NET_COMPACT_20 && TRACE_SHARED
          375  +              catch (Exception e)
          376  +#else
          377  +              catch (Exception)
          378  +#endif
          379  +              {
          380  +#if !NET_COMPACT_20 && TRACE_SHARED
          381  +                  try
          382  +                  {
          383  +                      Trace.WriteLine(HelperMethods.StringFormat(
          384  +                          CultureInfo.CurrentCulture,
          385  +                          "Failed to issue debugger prompt, " +
          386  +                          "{0} may be unusable: {1}",
          387  +                          typeof(Console), e)); /* throw */
          388  +                  }
          389  +                  catch
          390  +                  {
          391  +                      // do nothing.
          392  +                  }
          393  +#endif
          394  +              }
          395  +
          396  +              try
          397  +              {
          398  +                  Debugger.Break();
          399  +
          400  +                  lock (staticSyncRoot)
          401  +                  {
          402  +                      debuggerBreak = true;
          403  +                  }
          404  +              }
          405  +              catch
          406  +              {
          407  +                  lock (staticSyncRoot)
          408  +                  {
          409  +                      debuggerBreak = false;
          410  +                  }
          411  +
          412  +                  throw;
          413  +              }
          414  +          }
          415  +      }
          416  +
          417  +      /////////////////////////////////////////////////////////////////////////
          418  +
   310    419         /// <summary>
   311    420         /// Determines if preparing a query should be logged.
   312    421         /// </summary>
   313    422         /// <param name="flags">
   314    423         /// The flags associated with the parent connection object.
   315    424         /// </param>
   316    425         /// <returns>
................................................................................
   985   1094             //       anything), skip all our special code and simply return.
   986   1095             //
   987   1096             if (GetSettingValue("No_PreLoadSQLite", null) != null)
   988   1097                 return;
   989   1098   #endif
   990   1099   #endif
   991   1100   
         1101  +          //
         1102  +          // NOTE: Check if a debugger needs to be attached before
         1103  +          //       doing any real work.
         1104  +          //
         1105  +          HelperMethods.MaybeBreakIntoDebugger();
         1106  +
   992   1107             #region Debug Build Only
   993   1108   #if DEBUG
   994   1109             //
   995   1110             // NOTE: Create the lists of statistics that will contain
   996   1111             //       various counts used in debugging, including the
   997   1112             //       number of times each setting value has been read.
   998   1113             //