Skip to content

Commit 469bbac

Browse files
committed
Calling fb_shutdown on exit (DNET-806)
1 parent fccd7d1 commit 469bbac

File tree

7 files changed

+77
-45
lines changed

7 files changed

+77
-45
lines changed

Provider/src/FirebirdSql.Data.FirebirdClient/Client/Managed/Version10/GdsDatabase.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,7 @@ public virtual void Detach()
243243
#warning Here
244244
_xdrStream?.Dispose();
245245

246+
#warning Same as in Dispose
246247
_transactionCount = 0;
247248
_handle = -1;
248249
_dialect = 0;

Provider/src/FirebirdSql.Data.FirebirdClient/Client/Native/FbClientFactory.cs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
using System.Runtime.InteropServices;
2424
using System.Collections.Concurrent;
2525
using FirebirdSql.Data.Client.Native.Handle;
26+
using FirebirdSql.Data.Common;
2627

2728
namespace FirebirdSql.Data.Client.Native
2829
{
@@ -66,13 +67,19 @@ static FbClientFactory()
6667
/// </summary>
6768
/// <param name="dllName">The name of the DLL to load (e.g. "fbembed", "C:\path\to\fbembed.dll", etc)</param>
6869
/// <returns>A class that implements <see cref="IFbClient"/> and calls into the native library you specify.</returns>
69-
public static IFbClient GetFbClient(string dllName)
70+
public static IFbClient Create(string dllName)
7071
{
7172
if (string.IsNullOrEmpty(dllName))
7273
{
7374
dllName = DefaultDllName;
7475
}
75-
return cache.GetOrAdd(dllName, GenerateFbClient);
76+
var createdNew = false;
77+
var result = cache.GetOrAdd(dllName, s => { createdNew = true; return BuildFbClient(s); });
78+
if (createdNew)
79+
{
80+
ShutdownHelper.RegisterFbClientShutdown(() => result.fb_shutdown(0, 0));
81+
}
82+
return result;
7683
}
7784

7885
/// <summary>
@@ -86,7 +93,7 @@ public static IFbClient GetFbClient(string dllName)
8693
/// <para>Note: To be completly generic, we actually reflect through <see cref="IFbClient"/>
8794
/// to get the methods and parameters to generate.</para>
8895
/// </remarks>
89-
private static IFbClient GenerateFbClient(string dllName)
96+
private static IFbClient BuildFbClient(string dllName)
9097
{
9198
// Get the initial TypeBuilder, with a "blank" class definition
9299
var tb = CreateTypeBuilder(dllName);
@@ -253,7 +260,7 @@ private static IFbClient CreateInstance(TypeBuilder tb)
253260
/// <returns>A <see cref="TypeBuilder"/> which we can use for building our type.</returns>
254261
/// <remarks>
255262
/// <para>Notice that we actually generate a new assembly for every different <c>dllName</c> that is
256-
/// passed into <see cref="GenerateFbClient"/>. This might be inefficient, but since we're mostly
263+
/// passed into <see cref="BuildFbClient"/>. This might be inefficient, but since we're mostly
257264
/// only ever going to have one (or maybe two) different <c>dllName</c>s, it's not a big deal.</para>
258265
/// </remarks>
259266
private static TypeBuilder CreateTypeBuilder(string baseName)

Provider/src/FirebirdSql.Data.FirebirdClient/Client/Native/FesDatabase.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ public bool ConnectionBroken
116116

117117
public FesDatabase(string dllName, Charset charset)
118118
{
119-
_fbClient = FbClientFactory.GetFbClient(dllName);
119+
_fbClient = FbClientFactory.Create(dllName);
120120
_handle = new DatabaseHandle();
121121
_charset = charset ?? Charset.DefaultCharset;
122122
_dialect = 3;

Provider/src/FirebirdSql.Data.FirebirdClient/Client/Native/FesServiceManager.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ public Charset Charset
6363

6464
public FesServiceManager(string dllName, Charset charset)
6565
{
66-
_fbClient = FbClientFactory.GetFbClient(dllName);
66+
_fbClient = FbClientFactory.Create(dllName);
6767
_charset = charset ?? Charset.DefaultCharset;
6868
_statusVector = new IntPtr[IscCodes.ISC_STATUS_LENGTH];
6969
}

Provider/src/FirebirdSql.Data.FirebirdClient/Client/Native/IFbClient.cs

Lines changed: 6 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,9 @@
1515

1616
//$Authors = Carlos Guzman Alvarez, Dean Harding, Jiri Cincura (jiri@cincura.net)
1717

18-
using FirebirdSql.Data.Client.Native.Handle;
19-
using FirebirdSql.Data.Common;
2018
using System;
21-
using System.Diagnostics.Contracts;
2219
using System.Runtime.InteropServices;
20+
using FirebirdSql.Data.Client.Native.Handle;
2321

2422
namespace FirebirdSql.Data.Client.Native
2523
{
@@ -33,8 +31,6 @@ public interface IFbClient
3331
{
3432
#pragma warning disable IDE1006
3533

36-
#region Array Functions
37-
3834
IntPtr isc_array_get_slice(
3935
[In, Out] IntPtr[] statusVector,
4036
[MarshalAs(UnmanagedType.I4)] ref DatabaseHandle dbHandle,
@@ -53,10 +49,6 @@ IntPtr isc_array_put_slice(
5349
byte[] sourceArray,
5450
ref int sliceLength);
5551

56-
#endregion
57-
58-
#region Blob Functions
59-
6052
IntPtr isc_create_blob2(
6153
[In, Out] IntPtr[] statusVector,
6254
[MarshalAs(UnmanagedType.I4)] ref DatabaseHandle dbHandle,
@@ -96,10 +88,6 @@ IntPtr isc_close_blob(
9688
[In, Out] IntPtr[] statusVector,
9789
[MarshalAs(UnmanagedType.I4)] ref BlobHandle blobHandle);
9890

99-
#endregion
100-
101-
#region Database Functions
102-
10391
IntPtr isc_attach_database(
10492
[In, Out] IntPtr[] statusVector,
10593
short dbNameLength,
@@ -128,14 +116,11 @@ IntPtr isc_create_database(
128116
short parmBufferLength,
129117
byte[] parmBuffer,
130118
short dbType);
119+
131120
IntPtr isc_drop_database(
132121
[In, Out] IntPtr[] statusVector,
133122
[MarshalAs(UnmanagedType.I4)] ref DatabaseHandle dbHandle);
134123

135-
#endregion
136-
137-
#region Transaction Functions
138-
139124
IntPtr isc_start_multiple(
140125
[In, Out] IntPtr[] statusVector,
141126
[MarshalAs(UnmanagedType.I4)] ref TransactionHandle trHandle,
@@ -158,19 +143,15 @@ IntPtr isc_rollback_retaining(
158143
[In, Out] IntPtr[] statusVector,
159144
[MarshalAs(UnmanagedType.I4)] ref TransactionHandle trHandle);
160145

161-
#endregion
162-
163-
#region Cancel Functions
146+
IntPtr fb_shutdown(
147+
int timeout,
148+
int reason);
164149

165150
IntPtr fb_cancel_operation(
166151
[In, Out] IntPtr[] statusVector,
167152
[MarshalAs(UnmanagedType.I4)] ref DatabaseHandle dbHandle,
168153
int option);
169154

170-
#endregion
171-
172-
#region DSQL Functions
173-
174155
IntPtr isc_dsql_allocate_statement(
175156
[In, Out] IntPtr[] statusVector,
176157
[MarshalAs(UnmanagedType.I4)] ref DatabaseHandle dbHandle,
@@ -184,7 +165,7 @@ IntPtr isc_dsql_describe(
184165

185166
IntPtr isc_dsql_describe_bind(
186167
[In, Out] IntPtr[] statusVector,
187-
[MarshalAs(UnmanagedType.I4)] ref StatementHandle stmtHandle,
168+
[MarshalAs(UnmanagedType.I4)] ref StatementHandle stmtHandle,
188169
short daVersion,
189170
IntPtr xsqlda);
190171

@@ -231,14 +212,6 @@ IntPtr isc_dsql_sql_info(
231212
short bufferLength,
232213
byte[] buffer);
233214

234-
IntPtr isc_vax_integer(
235-
byte[] buffer,
236-
short length);
237-
238-
#endregion
239-
240-
#region Services Functions
241-
242215
IntPtr isc_service_attach(
243216
[In, Out] IntPtr[] statusVector,
244217
short serviceLength,
@@ -269,8 +242,6 @@ IntPtr isc_service_query(
269242
short bufferLength,
270243
byte[] buffer);
271244

272-
#endregion
273-
274245
#pragma warning restore IDE1006
275246
}
276247
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
* The contents of this file are subject to the Initial
3+
* Developer's Public License Version 1.0 (the "License");
4+
* you may not use this file except in compliance with the
5+
* License. You may obtain a copy of the License at
6+
* https://github.com/FirebirdSQL/NETProvider/blob/master/license.txt.
7+
*
8+
* Software distributed under the License is distributed on
9+
* an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
10+
* express or implied. See the License for the specific
11+
* language governing rights and limitations under the License.
12+
*
13+
* All Rights Reserved.
14+
*/
15+
16+
//$Authors = Jiri Cincura (jiri@cincura.net)
17+
18+
using System;
19+
using System.Collections.Concurrent;
20+
21+
namespace FirebirdSql.Data.Common
22+
{
23+
internal static class ShutdownHelper
24+
{
25+
static ConcurrentBag<Action> _pools;
26+
static ConcurrentBag<Action> _fbClients;
27+
28+
static ShutdownHelper()
29+
{
30+
_pools = new ConcurrentBag<Action>();
31+
_fbClients = new ConcurrentBag<Action>();
32+
#if !NETSTANDARD1_6
33+
AppDomain.CurrentDomain.DomainUnload += (sender, e) => HandleShutdown();
34+
AppDomain.CurrentDomain.ProcessExit += (sender, e) => HandleShutdown();
35+
#endif
36+
}
37+
38+
internal static void RegisterPoolCleanup(Action item)
39+
{
40+
_pools.Add(item);
41+
}
42+
43+
internal static void RegisterFbClientShutdown(Action item)
44+
{
45+
_fbClients.Add(item);
46+
}
47+
48+
static void HandleShutdown()
49+
{
50+
foreach (var item in _pools)
51+
item();
52+
foreach (var item in _fbClients)
53+
item();
54+
}
55+
}
56+
}

Provider/src/FirebirdSql.Data.FirebirdClient/FirebirdClient/FbConnectionPoolManager.cs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -184,10 +184,7 @@ FbConnectionInternal CreateNewConnectionIfPossibleImpl(FbConnectionString connec
184184
static FbConnectionPoolManager()
185185
{
186186
Instance = new FbConnectionPoolManager();
187-
#if !NETSTANDARD1_6
188-
AppDomain.CurrentDomain.DomainUnload += (sender, e) => Instance.Dispose();
189-
AppDomain.CurrentDomain.ProcessExit += (sender, e) => Instance.Dispose();
190-
#endif
187+
ShutdownHelper.RegisterPoolCleanup(Instance.Dispose);
191188
}
192189

193190
FbConnectionPoolManager()

0 commit comments

Comments
 (0)