From a254f5a3a8396865cf05e27e0ab03345ee66783a Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 24 Nov 2014 22:08:11 +0100 Subject: archive/zzip: fix inverted error handler Set the Error when zzip_seek()==-1 and not on success. Fixes a crash after seeking. --- src/archive/ZzipArchivePlugin.cxx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/archive/ZzipArchivePlugin.cxx b/src/archive/ZzipArchivePlugin.cxx index 973fe91dc..d3e4cc837 100644 --- a/src/archive/ZzipArchivePlugin.cxx +++ b/src/archive/ZzipArchivePlugin.cxx @@ -186,12 +186,13 @@ zzip_input_seek(InputStream *is, InputPlugin::offset_type offset, { ZzipInputStream *zis = (ZzipInputStream *)is; zzip_off_t ofs = zzip_seek(zis->file, offset, whence); - if (ofs != -1) { + if (ofs < 0) { error.Set(zzip_domain, "zzip_seek() has failed"); - is->offset = ofs; - return true; + return false; } - return false; + + is->offset = ofs; + return true; } /* exported structures */ -- cgit v1.2.3 From a8ebfd7a92a48676d753e3ca3ee3175f6ff4d62e Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 25 Nov 2014 10:43:39 +0100 Subject: event/DeferredMonitor: include cleanup --- src/event/DeferredMonitor.hxx | 3 --- src/input/plugins/AlsaInputPlugin.cxx | 2 ++ 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/event/DeferredMonitor.hxx b/src/event/DeferredMonitor.hxx index 3d3ab22b7..c4aa605fc 100644 --- a/src/event/DeferredMonitor.hxx +++ b/src/event/DeferredMonitor.hxx @@ -21,9 +21,6 @@ #define MPD_SOCKET_DEFERRED_MONITOR_HXX #include "check.h" -#include "Compiler.h" - -#include class EventLoop; diff --git a/src/input/plugins/AlsaInputPlugin.cxx b/src/input/plugins/AlsaInputPlugin.cxx index 82b96f7df..f03f745c6 100644 --- a/src/input/plugins/AlsaInputPlugin.cxx +++ b/src/input/plugins/AlsaInputPlugin.cxx @@ -43,6 +43,8 @@ #include +#include + #include #include -- cgit v1.2.3 From fa4d202e71e2ff59583e088d9512424e32d3d761 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 24 Nov 2014 22:18:31 +0100 Subject: decoder/mp4v2: remove because of incompatible license libmp4v2 is licensed under MPL 1.1, which is incompatible with GPLv2. Unfortunately, this means that we must remove the plugin. More information can be found in the Debian bug report: http://bugs.debian.org/767504 --- src/decoder/DecoderList.cxx | 4 - src/decoder/plugins/Mp4v2DecoderPlugin.cxx | 330 ----------------------------- src/decoder/plugins/Mp4v2DecoderPlugin.hxx | 25 --- 3 files changed, 359 deletions(-) delete mode 100644 src/decoder/plugins/Mp4v2DecoderPlugin.cxx delete mode 100644 src/decoder/plugins/Mp4v2DecoderPlugin.hxx (limited to 'src') diff --git a/src/decoder/DecoderList.cxx b/src/decoder/DecoderList.cxx index 0a31d9eac..cd6881ce2 100644 --- a/src/decoder/DecoderList.cxx +++ b/src/decoder/DecoderList.cxx @@ -37,7 +37,6 @@ #include "plugins/MadDecoderPlugin.hxx" #include "plugins/SndfileDecoderPlugin.hxx" #include "plugins/Mpg123DecoderPlugin.hxx" -#include "plugins/Mp4v2DecoderPlugin.hxx" #include "plugins/WildmidiDecoderPlugin.hxx" #include "plugins/MikmodDecoderPlugin.hxx" #include "plugins/ModplugDecoderPlugin.hxx" @@ -55,9 +54,6 @@ const struct DecoderPlugin *const decoder_plugins[] = { #ifdef HAVE_MPG123 &mpg123_decoder_plugin, #endif -#ifdef HAVE_MP4V2 - &mp4v2_decoder_plugin, -#endif #ifdef ENABLE_VORBIS_DECODER &vorbis_decoder_plugin, #endif diff --git a/src/decoder/plugins/Mp4v2DecoderPlugin.cxx b/src/decoder/plugins/Mp4v2DecoderPlugin.cxx deleted file mode 100644 index 34bccd243..000000000 --- a/src/decoder/plugins/Mp4v2DecoderPlugin.cxx +++ /dev/null @@ -1,330 +0,0 @@ -/* - * Copyright (C) 2003-2014 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "config.h" /* must be first for large file support */ -#include "Mp4v2DecoderPlugin.hxx" -#include "../DecoderAPI.hxx" -#include "CheckAudioFormat.hxx" -#include "tag/TagHandler.hxx" -#include "fs/Path.hxx" -#include "util/Error.hxx" -#include "util/Domain.hxx" -#include "Log.hxx" - -#include -#include - -#include -#include - -static constexpr Domain mp4v2_decoder_domain("mp4v2"); - -static MP4TrackId -mp4_get_aac_track(MP4FileHandle handle, NeAACDecHandle decoder, - AudioFormat &audio_format, Error &error) -{ - unsigned long sample_rate; - - const MP4TrackId tracks = MP4GetNumberOfTracks(handle); - - for (MP4TrackId id = 1; id <= tracks; id++) { - const char* track_type = MP4GetTrackType(handle, id); - - if (track_type == 0) - continue; - - const auto obj_type = MP4GetTrackEsdsObjectTypeId(handle, id); - - if (obj_type == MP4_INVALID_AUDIO_TYPE) - continue; - if (obj_type == MP4_MPEG4_AUDIO_TYPE) { - const auto mpeg_type = MP4GetTrackAudioMpeg4Type(handle, id); - if (!MP4_IS_MPEG4_AAC_AUDIO_TYPE(mpeg_type)) - continue; - } else if (!MP4_IS_AAC_AUDIO_TYPE(obj_type)) - continue; - - if (decoder == nullptr) - /* found audio track, no decoder */ - return id; - - unsigned char *buff = nullptr; - unsigned buff_size = 0; - - if (!MP4GetTrackESConfiguration(handle, id, &buff, &buff_size)) - continue; - - uint8_t channels; - int32_t nbytes = NeAACDecInit(decoder, buff, buff_size, - &sample_rate, &channels); - - free(buff); - - if (nbytes < 0) - /* invalid stream */ - continue; - - if (!audio_format_init_checked(audio_format, sample_rate, - SampleFormat::S16, - channels, - error)) - continue; - - return id; - } - - error.Set(mp4v2_decoder_domain, "no valid aac track found"); - - return MP4_INVALID_TRACK_ID; -} - -static NeAACDecHandle -mp4_faad_new(MP4FileHandle handle, AudioFormat &audio_format, Error &error) -{ - const NeAACDecHandle decoder = NeAACDecOpen(); - const NeAACDecConfigurationPtr config = - NeAACDecGetCurrentConfiguration(decoder); - config->outputFormat = FAAD_FMT_16BIT; - config->downMatrix = 1; - config->dontUpSampleImplicitSBR = 0; - NeAACDecSetConfiguration(decoder, config); - - const auto track = mp4_get_aac_track(handle, decoder, audio_format, error); - - if (track == MP4_INVALID_TRACK_ID) { - NeAACDecClose(decoder); - return nullptr; - } - - return decoder; -} - -static void -mp4_file_decode(Decoder &mpd_decoder, Path path_fs) -{ - const MP4FileHandle handle = MP4Read(path_fs.c_str()); - - if (handle == MP4_INVALID_FILE_HANDLE) { - FormatError(mp4v2_decoder_domain, - "unable to open file"); - return; - } - - AudioFormat audio_format; - Error error; - const NeAACDecHandle decoder = mp4_faad_new(handle, audio_format, error); - - if (decoder == nullptr) { - LogError(error); - MP4Close(handle); - return; - } - - const MP4TrackId track = mp4_get_aac_track(handle, nullptr, audio_format, error); - - /* initialize the MPD core */ - - const MP4Timestamp scale = MP4GetTrackTimeScale(handle, track); - const SongTime duration = SongTime::FromScale(MP4GetTrackDuration(handle, track), - scale); - const MP4SampleId num_samples = MP4GetTrackNumberOfSamples(handle, track); - - decoder_initialized(mpd_decoder, audio_format, true, duration); - - /* the decoder loop */ - - DecoderCommand cmd = DecoderCommand::NONE; - - for (MP4SampleId sample = 1; - sample < num_samples && cmd != DecoderCommand::STOP; - sample++) { - unsigned char *data = nullptr; - unsigned int data_length = 0; - - if (cmd == DecoderCommand::SEEK) { - const MP4Timestamp offset = - decoder_seek_time(mpd_decoder).ToScale(scale); - - sample = MP4GetSampleIdFromTime(handle, track, offset, - false); - decoder_command_finished(mpd_decoder); - } - - /* read */ - if (MP4ReadSample(handle, track, sample, &data, &data_length) == 0) { - FormatError(mp4v2_decoder_domain, "unable to read sample"); - break; - } - - /* decode it */ - NeAACDecFrameInfo frame_info; - const void *const decoded = NeAACDecDecode(decoder, &frame_info, data, data_length); - - if (frame_info.error > 0) { - FormatWarning(mp4v2_decoder_domain, - "error decoding AAC stream: %s", - NeAACDecGetErrorMessage(frame_info.error)); - break; - } - - if (frame_info.channels != audio_format.channels) { - FormatDefault(mp4v2_decoder_domain, - "channel count changed from %u to %u", - audio_format.channels, frame_info.channels); - break; - } - - if (frame_info.samplerate != audio_format.sample_rate) { - FormatDefault(mp4v2_decoder_domain, - "sample rate changed from %u to %lu", - audio_format.sample_rate, - (unsigned long)frame_info.samplerate); - break; - } - - /* update bit rate and position */ - unsigned bit_rate = 0; - - if (frame_info.samples > 0) { - bit_rate = frame_info.bytesconsumed * 8.0 * - frame_info.channels * audio_format.sample_rate / - frame_info.samples / 1000 + 0.5; - } - - /* send PCM samples to MPD */ - - cmd = decoder_data(mpd_decoder, nullptr, decoded, - (size_t)frame_info.samples * 2, - bit_rate); - - free(data); - } - - /* cleanup */ - NeAACDecClose(decoder); - MP4Close(handle); -} - -static inline void -mp4_safe_invoke_tag(const struct tag_handler *handler, void *handler_ctx, - TagType tag, const char *value) -{ - if (value != nullptr) - tag_handler_invoke_tag(handler, handler_ctx, tag, value); -} - -static bool -mp4_scan_file(Path path_fs, - const struct tag_handler *handler, void *handler_ctx) -{ - const MP4FileHandle handle = MP4Read(path_fs.c_str()); - - if (handle == MP4_INVALID_FILE_HANDLE) - return false; - - AudioFormat tmp_audio_format; - Error error; - const MP4TrackId id = mp4_get_aac_track(handle, nullptr, tmp_audio_format, error); - - if (id == MP4_INVALID_TRACK_ID) { - LogError(error); - MP4Close(handle); - return false; - } - - const MP4Timestamp scale = MP4GetTrackTimeScale(handle, id); - const SongTime dur = - SongTime::FromScale(MP4GetTrackDuration(handle, id), - scale); - tag_handler_invoke_duration(handler, handler_ctx, dur); - - const MP4Tags* tags = MP4TagsAlloc(); - MP4TagsFetch(tags, handle); - - static constexpr struct { - const char *MP4Tags::*p; - TagType tag_type; - } mp4v2_tags[] = { - { &MP4Tags::name, TAG_NAME }, - { &MP4Tags::artist, TAG_ARTIST }, - { &MP4Tags::albumArtist, TAG_ALBUM_ARTIST }, - { &MP4Tags::album, TAG_ALBUM }, - { &MP4Tags::composer, TAG_COMPOSER }, - { &MP4Tags::comments, TAG_COMMENT }, - { &MP4Tags::genre, TAG_GENRE }, - { &MP4Tags::releaseDate, TAG_DATE }, - { &MP4Tags::sortArtist, TAG_ARTIST_SORT }, - { &MP4Tags::sortAlbumArtist, TAG_ALBUM_ARTIST_SORT }, - }; - - for (const auto &i : mp4v2_tags) - mp4_safe_invoke_tag(handler, handler_ctx, - i.tag_type, tags->*i.p); - - char buff[8]; /* tmp buffer for index to string. */ - if (tags->track != nullptr) { - sprintf(buff, "%d", tags->track->index); - tag_handler_invoke_tag(handler, handler_ctx, TAG_TRACK, buff); - } - - if (tags->disk != nullptr) { - sprintf(buff, "%d", tags->disk->index); - tag_handler_invoke_tag(handler, handler_ctx, TAG_DISC, buff); - } - - MP4TagsFree(tags); - MP4Close(handle); - - return true; -} - -static const char *const mp4_suffixes[] = { - "mp4", - "m4a", - /* "m4p", encrypted */ - /* "m4b", audio book */ - /* "m4r", ring tones */ - /* "m4v", video */ - nullptr -}; - -static const char *const mp4_mime_types[] = { - "application/mp4", - "application/m4a", - "audio/mp4", - "audio/m4a", - /* "audio/m4p", */ - /* "audio/m4b", */ - /* "audio/m4r", */ - /* "audio/m4v", */ - nullptr -}; - -const struct DecoderPlugin mp4v2_decoder_plugin = { - "mp4v2", - nullptr, - nullptr, - nullptr, - mp4_file_decode, - mp4_scan_file, - nullptr, - nullptr, - mp4_suffixes, - mp4_mime_types -}; diff --git a/src/decoder/plugins/Mp4v2DecoderPlugin.hxx b/src/decoder/plugins/Mp4v2DecoderPlugin.hxx deleted file mode 100644 index 57585dec4..000000000 --- a/src/decoder/plugins/Mp4v2DecoderPlugin.hxx +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2003-2014 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef MPD_DECODER_MP4V2_HXX -#define MPD_DECODER_MP4V2_HXX - -extern const struct DecoderPlugin mp4v2_decoder_plugin; - -#endif -- cgit v1.2.3 From 029555d1921e651f1ed6929561a52eb598def3fb Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 25 Nov 2014 13:10:16 +0100 Subject: lib/nfs/FileReader: include Compiler.h for "final" fallback --- src/lib/nfs/FileReader.hxx | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/lib/nfs/FileReader.hxx b/src/lib/nfs/FileReader.hxx index 7f43e0ecf..424ff766d 100644 --- a/src/lib/nfs/FileReader.hxx +++ b/src/lib/nfs/FileReader.hxx @@ -24,6 +24,7 @@ #include "Lease.hxx" #include "Callback.hxx" #include "event/DeferredMonitor.hxx" +#include "Compiler.h" #include -- cgit v1.2.3 From f5f43db2da6bf0e5f39c8fb281ccca6e3dd8e65a Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 25 Nov 2014 13:09:19 +0100 Subject: lib/nfs/Connection: cancel DeferredMonitor on disconnect Fixes potential second mount attempt after the old connection to the NFS server was shut down. --- src/lib/nfs/Connection.cxx | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/lib/nfs/Connection.cxx b/src/lib/nfs/Connection.cxx index c2c7ceb2b..c4612f613 100644 --- a/src/lib/nfs/Connection.cxx +++ b/src/lib/nfs/Connection.cxx @@ -327,6 +327,10 @@ NfsConnection::DestroyContext() assert(GetEventLoop().IsInside()); assert(context != nullptr); + /* cancel pending DeferredMonitor that was scheduled to notify + new leases */ + DeferredMonitor::Cancel(); + if (SocketMonitor::IsDefined()) SocketMonitor::Cancel(); -- cgit v1.2.3 From b293b160079fd19cfc675fa86c2b99695aac171f Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 25 Nov 2014 13:27:06 +0100 Subject: lib/nfs/Connection: broadcast error before closing connection During the NfsLease::OnNfsConnectionFailed() call, the old (defunct) nfs_context may be used to close file handles. Such code does not yet exist, but will be added soon to fix other bugs. --- src/lib/nfs/Connection.cxx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/lib/nfs/Connection.cxx b/src/lib/nfs/Connection.cxx index c4612f613..06d2a4d2a 100644 --- a/src/lib/nfs/Connection.cxx +++ b/src/lib/nfs/Connection.cxx @@ -409,10 +409,10 @@ NfsConnection::OnSocketReady(unsigned flags) error.Format(nfs_domain, "NFS connection has failed: %s", nfs_get_error(context)); + BroadcastError(std::move(error)); + DestroyContext(); closed = true; - - BroadcastError(std::move(error)); } else if (SocketMonitor::IsDefined() && nfs_get_fd(context) < 0) { /* this happens when rpc_reconnect_requeue() is called after the connection broke, but autoreconnet was @@ -425,10 +425,10 @@ NfsConnection::OnSocketReady(unsigned flags) error.Format(nfs_domain, "NFS socket disappeared: %s", msg); + BroadcastError(std::move(error)); + DestroyContext(); closed = true; - - BroadcastError(std::move(error)); } assert(in_event); -- cgit v1.2.3 From 3cef348f30ad8a018b1c46f257d3e719be3f96b0 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 25 Nov 2014 10:42:52 +0100 Subject: lib/nfs/Manager: defer NfsConnection destruction Avoids a crash that occurs when NfsConnection::OnSocketReady() dereferences itself before returning. --- src/lib/nfs/Manager.cxx | 30 +++++++++++++++++++++++++----- src/lib/nfs/Manager.hxx | 33 +++++++++++++++++++++++++++++---- 2 files changed, 54 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/lib/nfs/Manager.cxx b/src/lib/nfs/Manager.cxx index c5aecf48d..6d50cce18 100644 --- a/src/lib/nfs/Manager.cxx +++ b/src/lib/nfs/Manager.cxx @@ -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(); +} diff --git a/src/lib/nfs/Manager.hxx b/src/lib/nfs/Manager.hxx index 612b01f9c..130c81aca 100644 --- a/src/lib/nfs/Manager.hxx +++ b/src/lib/nfs/Manager.hxx @@ -23,14 +23,16 @@ #include "check.h" #include "Connection.hxx" #include "Compiler.h" +#include "event/IdleMonitor.hxx" #include +#include /** * 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>, public boost::intrusive::set_base_hook> { 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 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 -- cgit v1.2.3 From 40dd968f1302da9fa65c53ba0ae0e6a12c7cda9b Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 25 Nov 2014 13:03:09 +0100 Subject: lib/nfs/FileReader: update "state" in OnNfsError() Clean up the "state" to indicate that there is no longer any asynchronous operation. Fixes another NFS-related crash due to cleanup of a non-existing asynchronous operation. --- src/lib/nfs/FileReader.cxx | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'src') diff --git a/src/lib/nfs/FileReader.cxx b/src/lib/nfs/FileReader.cxx index 4837e1f0e..7f5506d50 100644 --- a/src/lib/nfs/FileReader.cxx +++ b/src/lib/nfs/FileReader.cxx @@ -246,6 +246,30 @@ NfsFileReader::OnNfsCallback(unsigned status, void *data) void NfsFileReader::OnNfsError(Error &&error) { + switch (state) { + case State::INITIAL: + case State::DEFER: + case State::MOUNT: + case State::IDLE: + assert(false); + gcc_unreachable(); + + case State::OPEN: + connection->RemoveLease(*this); + state = State::INITIAL; + break; + + case State::STAT: + connection->RemoveLease(*this); + connection->Close(fh); + state = State::INITIAL; + break; + + case State::READ: + state = State::IDLE; + break; + } + OnNfsFileError(std::move(error)); } -- cgit v1.2.3 From 38f19981b2bcaa6f08f1d1e81be66d217e8da9b8 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 25 Nov 2014 13:50:36 +0100 Subject: lib/nfs/FileReader: reset state in OnNfsConnectionFailed() Avoid calling NfsConnection::RemoveLease(), because the lease has been removed already. --- src/lib/nfs/FileReader.cxx | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/lib/nfs/FileReader.cxx b/src/lib/nfs/FileReader.cxx index 7f5506d50..79256492b 100644 --- a/src/lib/nfs/FileReader.cxx +++ b/src/lib/nfs/FileReader.cxx @@ -164,6 +164,8 @@ NfsFileReader::OnNfsConnectionFailed(const Error &error) { assert(state == State::MOUNT); + state = State::INITIAL; + Error copy; copy.Set(error); OnNfsFileError(std::move(copy)); -- cgit v1.2.3 From 016063c810281bd05c792dfe8643cc68b4c3cab2 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 25 Nov 2014 14:00:32 +0100 Subject: lib/nfs/FileReader: move code to CancelOrClose() --- src/lib/nfs/FileReader.cxx | 10 ++++++++++ src/lib/nfs/FileReader.hxx | 6 ++++++ 2 files changed, 16 insertions(+) (limited to 'src') diff --git a/src/lib/nfs/FileReader.cxx b/src/lib/nfs/FileReader.cxx index 79256492b..455165bbd 100644 --- a/src/lib/nfs/FileReader.cxx +++ b/src/lib/nfs/FileReader.cxx @@ -56,8 +56,18 @@ NfsFileReader::Close() return; } + /* this cancels State::MOUNT */ connection->RemoveLease(*this); + CancelOrClose(); +} + +void +NfsFileReader::CancelOrClose() +{ + assert(state != State::INITIAL && + state != State::DEFER); + if (state == State::IDLE) /* no async operation in progress: can close immediately */ diff --git a/src/lib/nfs/FileReader.hxx b/src/lib/nfs/FileReader.hxx index 424ff766d..1495a2832 100644 --- a/src/lib/nfs/FileReader.hxx +++ b/src/lib/nfs/FileReader.hxx @@ -76,6 +76,12 @@ protected: virtual void OnNfsFileError(Error &&error) = 0; private: + /** + * Cancel the current operation, if any. The NfsLease must be + * unregistered already. + */ + void CancelOrClose(); + void OpenCallback(nfsfh *_fh); void StatCallback(const struct stat *st); -- cgit v1.2.3 From e72eef421b75516e0447e4a06419d1a7aba4d853 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 25 Nov 2014 12:29:55 +0100 Subject: lib/nfs/FileReader: clean up on disconnect Avoids crash because Close() invokes a call on a destructed NfsConnection. --- src/lib/nfs/FileReader.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/lib/nfs/FileReader.cxx b/src/lib/nfs/FileReader.cxx index 455165bbd..1b80f2c86 100644 --- a/src/lib/nfs/FileReader.cxx +++ b/src/lib/nfs/FileReader.cxx @@ -186,7 +186,7 @@ NfsFileReader::OnNfsConnectionDisconnected(const Error &error) { assert(state > State::MOUNT); - state = State::INITIAL; + CancelOrClose(); Error copy; copy.Set(error); -- cgit v1.2.3