On 27 April 2012 11:39, Larry Brasfield <larry_brasfi...@iinet.com> wrote:
> > When you use a collection of native code from managed code, and when that > native code has cleanup to do, defined by its own conventions rather than > the conventions established for the managed code system, you cannot count > on garbage collection to get the job done. In addition to memory > allocations, there are likely to be on-disk data and files that need to be > brought to a proper state when SQLite's designed close/exit mechanisms are > invoked. You "works as it should" is only assured (inasmuch as any > software can) when you use the .Net framework's assured disposition > mechanism ("using ..." and properly implemented IDispose) or effect the > equivalent in your own code. > > Yes thanks I'm familiar with using native resources from .net. After much more debugging I have found what I think is a bug. Some how SQLiteConnectionHandle is finalized but the weak reference.target returned from the pool is not null. Instead the weak reference returns a SQLiteConnectionHandle that has had Finalize called but the weakreference.IsAlive is true and the target is not null. I don't get it but that's what is happening. Our db code is sloppy so I'm not ruling out something we have done. However below I provide some code which will prevent the AccessViolationException exception and allow the application to function normally. > > So is this intended behaviour or a bug? I can try to come up with a test >> case that reproduces this if needed. >> > > It's not really intended behavior but intent cannot cure this problem > unless SQLite's finalizing API is used. > > I'm not sure I follow you. Users of System.Data.SQLite shouldn't have to concern themselves with calling dispose. Regardless of that, even if you do call dispose on the SQLiteConnection instance explicitly (or through a using statement) the underlying SQLiteConnectionHandle is added to the pool, where it can be garbage collected before it is removed. I was wrong when I said in my first post that this only happened when I let the connection be implicitly garbage collected. This would appear to be a problem with any SQLiteConnectionHandle added to the pool. I think the only reason our code exposed this is that we had many SQLiteConnectionHandle end up in the pool over a long period of time so the garbage collector hand a chance to run on those SQLiteConnectionHandle. For Joe: Anyway I've added the following code: in UnsafeNativeMethods.cs method ReleaseHandle() add handle = IntPtr.Zero; after SQLiteBase.CloseConnection(this); (I'd move the trace statement to the beginning of the function...) In SQLConnectionPool.cs, method Remove() approximately line 80 check for both null and !IsInvalid if (hdl != null && !hdl.IsInvalid) { return hdl; } This way it's impossible for the pool to return an invalid handle. With these changes our application runs without problems with pooling on. FWIW Our application performs all db access in a single thread, the main application thread. So I don't think it has to do with threads. I had started on a coming up with a test case, I'll try to finish it and see if I can reproduce it outside of our application. Thanks Greg. _______________________________________________ sqlite-users mailing list sqlite-users@sqlite.org http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users