Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
ruanhaishen
NLua
Commits
b21a53bc
Unverified
Commit
b21a53bc
authored
Feb 12, 2019
by
Vinicius Jarina
Committed by
GitHub
Feb 12, 2019
Browse files
Fixed cleanup of Lua objects on LuaBase finalizer. (#282)
* Fixed cleanup of Lua objects on LuaBase finalizer.
parent
f4866b5f
Changes
7
Show whitespace changes
Inline
Side-by-side
src/Lua.cs
View file @
b21a53bc
...
...
@@ -1084,9 +1084,15 @@ namespace NLua
}
#
endregion
internal
void
DisposeInternal
(
int
reference
)
internal
void
DisposeInternal
(
int
reference
,
bool
finalized
)
{
if
(
_luaState
!=
null
)
if
(
finalized
&&
_translator
!=
null
)
{
_translator
.
AddFinalizedReference
(
reference
);
return
;
}
if
(
_luaState
!=
null
&&
!
finalized
)
_luaState
.
Unref
(
reference
);
}
...
...
src/LuaBase.cs
View file @
b21a53bc
...
...
@@ -9,10 +9,22 @@ namespace NLua
{
private
bool
_disposed
;
protected
readonly
int
_Reference
;
protected
WeakReference
<
Lua
>
_
Interpreter
;
Lua
_
lua
;
protected
LuaBase
(
int
reference
)
protected
bool
TryGet
(
out
Lua
lua
)
{
if
(
_lua
.
State
==
null
)
{
lua
=
null
;
return
false
;
}
lua
=
_lua
;
return
true
;
}
protected
LuaBase
(
int
reference
,
Lua
lua
)
{
_lua
=
lua
;
_Reference
=
reference
;
}
...
...
@@ -27,27 +39,29 @@ namespace NLua
GC
.
SuppressFinalize
(
this
);
}
void
DisposeLuaReference
()
void
DisposeLuaReference
(
bool
finalized
)
{
if
(
_
Interpreter
==
null
)
if
(
_
lua
==
null
)
return
;
Lua
lua
;
if
(!
_Interpreter
.
TryGetTarg
et
(
out
lua
))
if
(!
TryG
et
(
out
lua
))
return
;
lua
.
DisposeInternal
(
_Reference
);
lua
.
DisposeInternal
(
_Reference
,
finalized
);
}
public
virtual
void
Dispose
(
bool
disposeManagedResources
)
{
if
(
_disposed
)
return
;
// TODO: Remove the disposeManagedResources check
if
(
_Reference
!=
0
&&
disposeManagedResources
)
bool
finalized
=
!
disposeManagedResources
;
if
(
_Reference
!=
0
)
{
DisposeLuaReference
();
DisposeLuaReference
(
finalized
);
}
_
Interpreter
=
null
;
_
lua
=
null
;
_disposed
=
true
;
}
...
...
@@ -58,7 +72,7 @@ namespace NLua
return
false
;
Lua
lua
;
if
(!
_Interpreter
.
TryGetTarg
et
(
out
lua
))
if
(!
TryG
et
(
out
lua
))
return
false
;
return
lua
.
CompareRef
(
reference
.
_Reference
,
_Reference
);
...
...
src/LuaFunction.cs
View file @
b21a53bc
...
...
@@ -10,16 +10,14 @@ namespace NLua
{
internal
readonly
LuaNativeFunction
function
;
public
LuaFunction
(
int
reference
,
Lua
interpreter
):
base
(
reference
)
public
LuaFunction
(
int
reference
,
Lua
interpreter
):
base
(
reference
,
interpreter
)
{
function
=
null
;
_Interpreter
=
new
WeakReference
<
Lua
>(
interpreter
);
}
public
LuaFunction
(
LuaNativeFunction
nativeFunction
,
Lua
interpreter
):
base
(
0
)
public
LuaFunction
(
LuaNativeFunction
nativeFunction
,
Lua
interpreter
):
base
(
0
,
interpreter
)
{
function
=
nativeFunction
;
_Interpreter
=
new
WeakReference
<
Lua
>(
interpreter
);
}
/*
...
...
@@ -29,7 +27,7 @@ namespace NLua
internal
object
[]
Call
(
object
[]
args
,
Type
[]
returnTypes
)
{
Lua
lua
;
if
(!
_Interpreter
.
TryGetTarg
et
(
out
lua
))
if
(!
TryG
et
(
out
lua
))
return
null
;
return
lua
.
CallFunction
(
this
,
args
,
returnTypes
);
...
...
@@ -42,8 +40,9 @@ namespace NLua
public
object
[]
Call
(
params
object
[]
args
)
{
Lua
lua
;
if
(!
_Interpreter
.
TryGetTarg
et
(
out
lua
))
if
(!
TryG
et
(
out
lua
))
return
null
;
return
lua
.
CallFunction
(
this
,
args
);
}
...
...
@@ -53,7 +52,7 @@ namespace NLua
internal
void
Push
(
LuaState
luaState
)
{
Lua
lua
;
if
(!
_Interpreter
.
TryGetTarg
et
(
out
lua
))
if
(!
TryG
et
(
out
lua
))
return
;
if
(
_Reference
!=
0
)
...
...
@@ -75,7 +74,7 @@ namespace NLua
return
false
;
Lua
lua
;
if
(!
_Interpreter
.
TryGetTarg
et
(
out
lua
))
if
(!
TryG
et
(
out
lua
))
return
false
;
if
(
_Reference
!=
0
&&
l
.
_Reference
!=
0
)
...
...
src/LuaTable.cs
View file @
b21a53bc
...
...
@@ -10,9 +10,8 @@ namespace NLua
{
public
class
LuaTable
:
LuaBase
{
public
LuaTable
(
int
reference
,
Lua
interpreter
):
base
(
reference
)
public
LuaTable
(
int
reference
,
Lua
interpreter
):
base
(
reference
,
interpreter
)
{
_Interpreter
=
new
WeakReference
<
Lua
>(
interpreter
);
}
/*
...
...
@@ -22,14 +21,14 @@ namespace NLua
get
{
Lua
lua
;
if
(!
_Interpreter
.
TryGetTarg
et
(
out
lua
))
if
(!
TryG
et
(
out
lua
))
return
null
;
return
lua
.
GetObject
(
_Reference
,
field
);
}
set
{
Lua
lua
;
if
(!
_Interpreter
.
TryGetTarg
et
(
out
lua
))
if
(!
TryG
et
(
out
lua
))
return
;
lua
.
SetObject
(
_Reference
,
field
,
value
);
}
...
...
@@ -42,7 +41,7 @@ namespace NLua
get
{
Lua
lua
;
if
(!
_Interpreter
.
TryGetTarg
et
(
out
lua
))
if
(!
TryG
et
(
out
lua
))
return
null
;
return
lua
.
GetObject
(
_Reference
,
field
);
...
...
@@ -50,7 +49,7 @@ namespace NLua
set
{
Lua
lua
;
if
(!
_Interpreter
.
TryGetTarg
et
(
out
lua
))
if
(!
TryG
et
(
out
lua
))
return
;
lua
.
SetObject
(
_Reference
,
field
,
value
);
...
...
@@ -60,7 +59,7 @@ namespace NLua
public
IDictionaryEnumerator
GetEnumerator
()
{
Lua
lua
;
if
(!
_Interpreter
.
TryGetTarg
et
(
out
lua
))
if
(!
TryG
et
(
out
lua
))
return
null
;
return
lua
.
GetTableDict
(
this
).
GetEnumerator
();
...
...
@@ -71,7 +70,7 @@ namespace NLua
get
{
Lua
lua
;
if
(!
_Interpreter
.
TryGetTarg
et
(
out
lua
))
if
(!
TryG
et
(
out
lua
))
return
null
;
return
lua
.
GetTableDict
(
this
).
Keys
;
...
...
@@ -84,7 +83,7 @@ namespace NLua
get
{
Lua
lua
;
if
(!
_Interpreter
.
TryGetTarg
et
(
out
lua
))
if
(!
TryG
et
(
out
lua
))
return
null
;
return
lua
.
GetTableDict
(
this
).
Values
;
...
...
@@ -99,7 +98,7 @@ namespace NLua
internal
object
RawGet
(
string
field
)
{
Lua
lua
;
if
(!
_Interpreter
.
TryGetTarg
et
(
out
lua
))
if
(!
TryG
et
(
out
lua
))
return
null
;
return
lua
.
RawGetObject
(
_Reference
,
field
);
...
...
src/LuaUserData.cs
View file @
b21a53bc
...
...
@@ -5,9 +5,8 @@ namespace NLua
{
public
class
LuaUserData
:
LuaBase
{
public
LuaUserData
(
int
reference
,
Lua
interpreter
):
base
(
reference
)
public
LuaUserData
(
int
reference
,
Lua
interpreter
):
base
(
reference
,
interpreter
)
{
_Interpreter
=
new
WeakReference
<
Lua
>(
interpreter
);
}
/*
...
...
@@ -17,7 +16,7 @@ namespace NLua
get
{
Lua
lua
;
if
(!
_Interpreter
.
TryGetTarg
et
(
out
lua
))
if
(!
TryG
et
(
out
lua
))
return
null
;
return
lua
.
GetObject
(
_Reference
,
field
);
...
...
@@ -25,7 +24,7 @@ namespace NLua
set
{
Lua
lua
;
if
(!
_Interpreter
.
TryGetTarg
et
(
out
lua
))
if
(!
TryG
et
(
out
lua
))
return
;
lua
.
SetObject
(
_Reference
,
field
,
value
);
...
...
@@ -39,7 +38,7 @@ namespace NLua
get
{
Lua
lua
;
if
(!
_Interpreter
.
TryGetTarg
et
(
out
lua
))
if
(!
TryG
et
(
out
lua
))
return
null
;
return
lua
.
GetObject
(
_Reference
,
field
);
...
...
@@ -47,7 +46,7 @@ namespace NLua
set
{
Lua
lua
;
if
(!
_Interpreter
.
TryGetTarg
et
(
out
lua
))
if
(!
TryG
et
(
out
lua
))
return
;
lua
.
SetObject
(
_Reference
,
field
,
value
);
...
...
@@ -61,7 +60,7 @@ namespace NLua
public
object
[]
Call
(
params
object
[]
args
)
{
Lua
lua
;
if
(!
_Interpreter
.
TryGetTarg
et
(
out
lua
))
if
(!
TryG
et
(
out
lua
))
return
null
;
return
lua
.
CallFunction
(
this
,
args
);
...
...
src/ObjectTranslator.cs
View file @
b21a53bc
...
...
@@ -49,6 +49,9 @@ namespace NLua
readonly
Dictionary
<
object
,
int
>
_objectsBackMap
=
new
Dictionary
<
object
,
int
>(
new
ReferenceComparer
());
// object # to object (FIXME - it should be possible to get object address as an object #)
readonly
Dictionary
<
int
,
object
>
_objects
=
new
Dictionary
<
int
,
object
>();
readonly
Queue
<
int
>
finalizedReferences
=
new
Queue
<
int
>();
internal
EventHandlerContainer
PendingEvents
=
new
EventHandlerContainer
();
MetaFunctions
metaFunctions
;
List
<
Assembly
>
assemblies
;
...
...
@@ -851,6 +854,9 @@ namespace NLua
*/
internal
LuaTable
GetTable
(
LuaState
luaState
,
int
index
)
{
// Before create new tables, check if there is any finalized object to clean.
CleanFinalizedReferences
(
luaState
);
luaState
.
PushCopy
(
index
);
int
reference
=
luaState
.
Ref
(
LuaRegistry
.
Index
);
if
(
reference
==
-
1
)
...
...
@@ -863,6 +869,9 @@ namespace NLua
*/
internal
LuaUserData
GetUserData
(
LuaState
luaState
,
int
index
)
{
// Before create new tables, check if there is any finalized object to clean.
CleanFinalizedReferences
(
luaState
);
luaState
.
PushCopy
(
index
);
int
reference
=
luaState
.
Ref
(
LuaRegistry
.
Index
);
if
(
reference
==
-
1
)
...
...
@@ -875,6 +884,9 @@ namespace NLua
*/
internal
LuaFunction
GetFunction
(
LuaState
luaState
,
int
index
)
{
// Before create new tables, check if there is any finalized object to clean.
CleanFinalizedReferences
(
luaState
);
luaState
.
PushCopy
(
index
);
int
reference
=
luaState
.
Ref
(
LuaRegistry
.
Index
);
if
(
reference
==
-
1
)
...
...
@@ -1102,5 +1114,22 @@ namespace NLua
PushObject
(
luaState
,
res
,
"luaNet_metatable"
);
return
1
;
}
internal
void
AddFinalizedReference
(
int
reference
)
{
finalizedReferences
.
Enqueue
(
reference
);
}
void
CleanFinalizedReferences
(
LuaState
state
)
{
if
(
finalizedReferences
.
Count
==
0
)
return
;
while
(
finalizedReferences
.
Count
!=
0
)
{
int
reference
=
finalizedReferences
.
Dequeue
();
state
.
Unref
(
LuaRegistry
.
Index
,
reference
);
}
}
}
}
\ No newline at end of file
tests/src/LuaTests.cs
View file @
b21a53bc
...
...
@@ -2,8 +2,7 @@
using
System.Text
;
using
System.Reflection
;
using
System.Threading
;
using
KeraLua
;
using
NLua
;
using
NLua.Exceptions
;
...
...
@@ -13,6 +12,9 @@ using NLuaTest.TestTypes;
using
NUnit.Framework
;
using
Lua
=
NLua
.
Lua
;
using
LuaFunction
=
NLua
.
LuaFunction
;
// ReSharper disable StringLiteralTypo
namespace
NLuaTest
...
...
@@ -2350,6 +2352,80 @@ namespace NLuaTest
}
}
[
Test
]
public
static
void
TestUseLuaObjectAfterDisposeShouldNotCrash
()
{
LuaTable
table
;
LuaFunction
function
;
using
(
var
lua
=
new
Lua
())
{
lua
.
DoString
(
"function F(a) return 2*a end"
);
function
=
lua
.
GetFunction
(
"F"
);
table
=
lua
.
DoString
(
"return { foo =\"Um dois tres\"}"
)
[
0
]
as
LuaTable
;
}
Assert
.
IsNotNull
(
function
);
Assert
.
IsNotNull
(
table
);
Assert
.
IsNull
(
table
[
"foo"
]);
var
result
=
function
.
Call
(
2
);
Assert
.
IsNull
(
result
);
}
void
ImplicitlyCreateATable
(
Lua
lua
)
{
var
x
=
lua
.
DoString
(
"return { foo = 1, bar = { la = 1 , la2 = 3, la4 = \"aidsjiasjdiasjdiajsdi\"} }"
)[
0
]
as
LuaTable
;
var
foo
=
x
[
"foo"
];
x
=
null
;
}
void
PleaseRunFinalizers
()
{
for
(
int
i
=
0
;
i
<
5
;
i
++)
{
GC
.
Collect
();
GC
.
WaitForPendingFinalizers
();
Thread
.
Sleep
(
0
);
}
}
///*
// * Tests if Lua objects are being released on finalizer
// */
[
Test
]
public
void
TestTableFinalizerDispose
()
{
using
(
Lua
lua
=
new
Lua
())
{
int
before
=
lua
.
State
.
GarbageCollector
(
LuaGC
.
Count
,
0
);
for
(
int
i
=
0
;
i
<
1000
;
i
++)
ImplicitlyCreateATable
(
lua
);
int
after1
=
lua
.
State
.
GarbageCollector
(
LuaGC
.
Count
,
0
);
PleaseRunFinalizers
();
ImplicitlyCreateATable
(
lua
);
lua
.
State
.
GarbageCollector
(
LuaGC
.
Collect
,
0
);
int
after2
=
lua
.
State
.
GarbageCollector
(
LuaGC
.
Count
,
0
);
int
ratio
=
after2
/
before
;
int
ratio2
=
after1
/
after2
;
// The ratio two is very uncertain, lets use 5x, just to have some certain that
// the gc collect the tables
Assert
.
True
(
ratio2
>=
5
,
"#1:"
+
ratio2
);
Assert
.
True
(
ratio
<=
1
,
"#2:"
+
ratio
);
}
}
static
Lua
m_lua
;
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment