Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
M
mpd
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Иван Мажукин
mpd
Commits
3cef348f
Commit
3cef348f
authored
Nov 25, 2014
by
Max Kellermann
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
lib/nfs/Manager: defer NfsConnection destruction
Avoids a crash that occurs when NfsConnection::OnSocketReady() dereferences itself before returning.
parent
b293b160
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
56 additions
and
9 deletions
+56
-9
NEWS
NEWS
+2
-0
Manager.cxx
src/lib/nfs/Manager.cxx
+25
-5
Manager.hxx
src/lib/nfs/Manager.hxx
+29
-4
No files found.
NEWS
View file @
3cef348f
ver 0.19.5 (not yet released)
* input
- nfs: fix crash on connection failure
* decoder
- dsdiff, dsf, opus: fix deadlock while seeking
- mp4v2: remove because of incompatible license
...
...
src/lib/nfs/Manager.cxx
View file @
3cef348f
...
...
@@ -29,8 +29,10 @@ NfsManager::ManagedConnection::OnNfsConnectionError(Error &&error)
{
FormatError
(
error
,
"NFS error on %s:%s"
,
GetServer
(),
GetExportName
());
manager
.
connections
.
erase
(
manager
.
connections
.
iterator_to
(
*
this
));
delete
this
;
/* defer deletion so the caller
(i.e. NfsConnection::OnSocketReady()) can still use this
object */
manager
.
ScheduleDelete
(
*
this
);
}
inline
bool
...
...
@@ -59,7 +61,9 @@ NfsManager::Compare::operator()(const ManagedConnection &a,
NfsManager
::~
NfsManager
()
{
assert
(
loop
.
IsInside
());
assert
(
GetEventLoop
().
IsInside
());
CollectGarbage
();
connections
.
clear_and_dispose
([](
ManagedConnection
*
c
){
delete
c
;
...
...
@@ -71,13 +75,13 @@ NfsManager::GetConnection(const char *server, const char *export_name)
{
assert
(
server
!=
nullptr
);
assert
(
export_name
!=
nullptr
);
assert
(
loop
.
IsInside
());
assert
(
GetEventLoop
()
.
IsInside
());
Map
::
insert_commit_data
hint
;
auto
result
=
connections
.
insert_check
(
LookupKey
{
server
,
export_name
},
Compare
(),
hint
);
if
(
result
.
second
)
{
auto
c
=
new
ManagedConnection
(
*
this
,
loop
,
auto
c
=
new
ManagedConnection
(
*
this
,
GetEventLoop
()
,
server
,
export_name
);
connections
.
insert_commit
(
*
c
,
hint
);
return
*
c
;
...
...
@@ -85,3 +89,19 @@ NfsManager::GetConnection(const char *server, const char *export_name)
return
*
result
.
first
;
}
}
void
NfsManager
::
CollectGarbage
()
{
assert
(
GetEventLoop
().
IsInside
());
garbage
.
clear_and_dispose
([](
ManagedConnection
*
c
){
delete
c
;
});
}
void
NfsManager
::
OnIdle
()
{
CollectGarbage
();
}
src/lib/nfs/Manager.hxx
View file @
3cef348f
...
...
@@ -23,14 +23,16 @@
#include "check.h"
#include "Connection.hxx"
#include "Compiler.h"
#include "event/IdleMonitor.hxx"
#include <boost/intrusive/set.hpp>
#include <boost/intrusive/slist.hpp>
/**
* A manager for NFS connections. Handles multiple connections to
* multiple NFS servers.
*/
class
NfsManager
{
class
NfsManager
final
:
IdleMonitor
{
struct
LookupKey
{
const
char
*
server
;
const
char
*
export_name
;
...
...
@@ -38,6 +40,7 @@ class NfsManager {
class
ManagedConnection
final
:
public
NfsConnection
,
public
boost
::
intrusive
::
slist_base_hook
<
boost
::
intrusive
::
link_mode
<
boost
::
intrusive
::
normal_link
>>
,
public
boost
::
intrusive
::
set_base_hook
<
boost
::
intrusive
::
link_mode
<
boost
::
intrusive
::
normal_link
>>
{
NfsManager
&
manager
;
...
...
@@ -63,8 +66,6 @@ class NfsManager {
const
LookupKey
b
)
const
;
};
EventLoop
&
loop
;
/**
* Maps server and export_name to #ManagedConnection.
*/
...
...
@@ -74,9 +75,18 @@ class NfsManager {
Map
connections
;
typedef
boost
::
intrusive
::
slist
<
ManagedConnection
>
List
;
/**
* A list of "garbage" connection objects. Their destruction
* is postponed because they were thrown into the garbage list
* when callers on the stack were still using them.
*/
List
garbage
;
public
:
NfsManager
(
EventLoop
&
_loop
)
:
loop
(
_loop
)
{}
:
IdleMonitor
(
_loop
)
{}
/**
* Must be run from EventLoop's thread.
...
...
@@ -86,6 +96,21 @@ public:
gcc_pure
NfsConnection
&
GetConnection
(
const
char
*
server
,
const
char
*
export_name
);
private
:
void
ScheduleDelete
(
ManagedConnection
&
c
)
{
connections
.
erase
(
connections
.
iterator_to
(
c
));
garbage
.
push_front
(
c
);
IdleMonitor
::
Schedule
();
}
/**
* Delete all connections on the #garbage list.
*/
void
CollectGarbage
();
/* virtual methods from IdleMonitor */
void
OnIdle
()
override
;
};
#endif
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