Compare commits

...

9 Commits

Author SHA1 Message Date
Max Kellermann
0a033fb10a release v0.20.4 2017-02-01 21:59:36 +01:00
Max Kellermann
591afa0647 lib/nfs/Connection: detect socket hangup and unregister from epoll
Fixes race condition when epoll_ctl() gets called after the socket has
been closed, which may affect a different socket created by another
thread meanwhile.
2017-02-01 21:44:20 +01:00
Max Kellermann
05eac20ffe lib/nfs/Connection: detect libnfs reconnect
When rpc_reconnect_requeue() gets called from inside nfs_service(),
the NfsInputStream can stall completely because the old socket has
been unregistered from epoll automatically, but the new one has never
been registered.  Therefore, nfs_service() will never be called again.

This kludge attempts to detect this condition by checking
nfs_which_events()==POLLOUT.

https://bugs.musicpd.org/view.php?id=4081
2017-02-01 21:36:58 +01:00
Max Kellermann
38d263ac19 output/sndio: work around a libroar C++ incompatibility
Same as in commit e02d8ad8d2, but this time for the sndio plugin
which can be emulated by libroar.
2017-02-01 19:53:23 +01:00
Thomas Zander
f71c204eef Correct method types to match Interface.hxx 2017-01-31 21:22:02 +01:00
Thomas Zander
51147203be free() require cstdlib to be included 2017-01-31 21:21:37 +01:00
Max Kellermann
a931686317 pcm/SampleFormat: workaround for GCC 4.9 "constexpr" bug
GCC 4.9 has incomplete C++14 support.  Specifically, it doesn't allow
switch/case in "constexpr" functions.
2017-01-27 11:02:58 +01:00
Max Kellermann
5bd322bdcf python/libs: upgrade Opus to 1.1.4 2017-01-27 08:47:58 +01:00
Max Kellermann
bb097109f0 configure.ac: prepare for 0.20.4 2017-01-27 08:47:36 +01:00
12 changed files with 60 additions and 44 deletions

8
NEWS
View File

@@ -1,3 +1,11 @@
ver 0.20.4 (2017/02/01)
* input
- nfs: fix freeze after reconnect
* output
- sndio: work around a libroar C++ incompatibility
* workaround for GCC 4.9 "constexpr" bug
* fix FreeBSD build failure
ver 0.20.3 (2017/01/25)
* protocol
- "playlistadd" creates new playlist if it does not exist, as documented

View File

@@ -1,10 +1,10 @@
AC_PREREQ(2.60)
AC_INIT(mpd, 0.20.3, musicpd-dev-team@lists.sourceforge.net)
AC_INIT(mpd, 0.20.4, musicpd-dev-team@lists.sourceforge.net)
VERSION_MAJOR=0
VERSION_MINOR=20
VERSION_REVISION=3
VERSION_REVISION=4
VERSION_EXTRA=0
AC_CONFIG_SRCDIR([src/Main.cxx])

View File

@@ -19,8 +19,8 @@ libvorbis = AutotoolsProject(
)
opus = AutotoolsProject(
'http://downloads.xiph.org/releases/opus/opus-1.1.3.tar.gz',
'32bbb6b557fe1b6066adc0ae1f08b629',
'http://downloads.xiph.org/releases/opus/opus-1.1.4.tar.gz',
'9122b6b380081dd2665189f97bfd777f04f92dc3ab6698eea1dbb27ad59d8692',
'lib/libopus.a',
['--disable-shared', '--enable-static'],
)

View File

@@ -62,7 +62,7 @@ Print(Response &r, TagType group, const TagCountMap &m)
}
}
static bool
static void
stats_visitor_song(SearchStats &stats, const LightSong &song)
{
stats.n_songs++;
@@ -70,8 +70,6 @@ stats_visitor_song(SearchStats &stats, const LightSong &song)
const auto duration = song.GetDuration();
if (!duration.IsNegative())
stats.total_duration += duration;
return true;
}
static bool
@@ -94,7 +92,7 @@ CollectGroupCounts(TagCountMap &map, TagType group, const Tag &tag)
return found;
}
static bool
static void
GroupCountVisitor(TagCountMap &map, TagType group, const LightSong &song)
{
assert(song.tag != nullptr);
@@ -103,8 +101,6 @@ GroupCountVisitor(TagCountMap &map, TagType group, const LightSong &song)
if (!CollectGroupCounts(map, group, tag) && group == TAG_ALBUM_ARTIST)
/* fall back to "Artist" if no "AlbumArtist" was found */
CollectGroupCounts(map, TAG_ARTIST, tag);
return true;
}
void

View File

@@ -27,13 +27,12 @@
#include <functional>
static bool
static void
AddSong(const Storage &storage, const char *playlist_path_utf8,
const LightSong &song)
{
spl_append_song(playlist_path_utf8,
DatabaseDetachSong(storage, song));
return true;
}
void

View File

@@ -49,16 +49,14 @@ PrintDirectoryURI(Response &r, bool base, const LightDirectory &directory)
ApplyBaseFlag(directory.GetPath(), base));
}
static bool
static void
PrintDirectoryBrief(Response &r, bool base, const LightDirectory &directory)
{
if (!directory.IsRoot())
PrintDirectoryURI(r, base, directory);
return true;
}
static bool
static void
PrintDirectoryFull(Response &r, bool base, const LightDirectory &directory)
{
if (!directory.IsRoot()) {
@@ -67,8 +65,6 @@ PrintDirectoryFull(Response &r, bool base, const LightDirectory &directory)
if (directory.mtime > 0)
time_print(r, "Last-Modified", directory.mtime);
}
return true;
}
static void
@@ -96,7 +92,7 @@ print_playlist_in_directory(Response &r, bool base,
directory->GetPath(), name_utf8);
}
static bool
static void
PrintSongBrief(Response &r, Partition &partition,
bool base, const LightSong &song)
{
@@ -106,11 +102,9 @@ PrintSongBrief(Response &r, Partition &partition,
/* this song file has an embedded CUE sheet */
print_playlist_in_directory(r, base,
song.directory, song.uri);
return true;
}
static bool
static void
PrintSongFull(Response &r, Partition &partition,
bool base, const LightSong &song)
{
@@ -120,21 +114,18 @@ PrintSongFull(Response &r, Partition &partition,
/* this song file has an embedded CUE sheet */
print_playlist_in_directory(r, base,
song.directory, song.uri);
return true;
}
static bool
static void
PrintPlaylistBrief(Response &r, bool base,
const PlaylistInfo &playlist,
const LightDirectory &directory)
{
print_playlist_in_directory(r, base,
&directory, playlist.name.c_str());
return true;
}
static bool
static void
PrintPlaylistFull(Response &r, bool base,
const PlaylistInfo &playlist,
const LightDirectory &directory)
@@ -144,8 +135,6 @@ PrintPlaylistFull(Response &r, bool base,
if (playlist.mtime > 0)
time_print(r, "Last-Modified", playlist.mtime);
return true;
}
void
@@ -191,15 +180,13 @@ db_selection_print(Response &r, Partition &partition,
0, std::numeric_limits<int>::max());
}
static bool
static void
PrintSongURIVisitor(Response &r, Partition &partition, const LightSong &song)
{
song_print_uri(r, partition, song);
return true;
}
static bool
static void
PrintUniqueTag(Response &r, TagType tag_type,
const Tag &tag)
{
@@ -211,8 +198,6 @@ PrintUniqueTag(Response &r, TagType tag_type,
if (item.type != tag_type)
r.Format("%s: %s\n",
tag_item_names[item.type], item.value);
return true;
}
void

View File

@@ -27,14 +27,13 @@
#include <functional>
static bool
static void
AddToQueue(Partition &partition, const LightSong &song)
{
const Storage &storage = *partition.instance.storage;
partition.playlist.AppendSong(partition.pc,
DatabaseDetachSong(storage,
song));
return true;
}
void

View File

@@ -67,15 +67,13 @@ StatsVisitTag(DatabaseStats &stats, StringSet &artists, StringSet &albums,
}
}
static bool
static void
StatsVisitSong(DatabaseStats &stats, StringSet &artists, StringSet &albums,
const LightSong &song)
{
++stats.song_count;
StatsVisitTag(stats, artists, albums, *song.tag);
return true;
}
DatabaseStats

View File

@@ -396,6 +396,17 @@ NfsConnection::ScheduleSocket()
assert(GetEventLoop().IsInside());
assert(context != nullptr);
const int which_events = nfs_which_events(context);
if (which_events == POLLOUT && SocketMonitor::IsDefined())
/* kludge: if libnfs asks only for POLLOUT, it means
that it is currently waiting for the connect() to
finish - rpc_reconnect_requeue() may have been
called from inside nfs_service(); we must now
unregister the old socket and register the new one
instead */
SocketMonitor::Steal();
if (!SocketMonitor::IsDefined()) {
int _fd = nfs_get_fd(context);
if (_fd < 0)
@@ -405,7 +416,8 @@ NfsConnection::ScheduleSocket()
SocketMonitor::Open(_fd);
}
SocketMonitor::Schedule(libnfs_to_events(nfs_which_events(context)));
SocketMonitor::Schedule(libnfs_to_events(which_events)
| SocketMonitor::HANGUP);
}
inline int
@@ -442,10 +454,14 @@ NfsConnection::OnSocketReady(unsigned flags)
bool closed = false;
const bool was_mounted = mount_finished;
if (!mount_finished)
if (!mount_finished || (flags & SocketMonitor::HANGUP) != 0)
/* until the mount is finished, the NFS client may use
various sockets, therefore we unregister and
re-register it each time */
/* also re-register the socket if we got a HANGUP,
which is a sure sign that libnfs will close the
socket, which can lead to a race condition if
epoll_ctl() is called later */
SocketMonitor::Steal();
const int result = Service(flags);

View File

@@ -24,8 +24,16 @@
#include "util/Domain.hxx"
#include "Log.hxx"
/* work around a C++ incompatibility if the sndio API is emulated by
libroar: libroar's "struct roar_service_stream" has a member named
"new", which is an illegal identifier in C++ */
#define new new_
#include <sndio.h>
/* undo the libroar workaround */
#undef new
#include <stdexcept>
#ifndef SIO_DEVANY

View File

@@ -64,7 +64,10 @@ enum class SampleFormat : uint8_t {
/**
* Checks whether the sample format is valid.
*/
static constexpr inline bool
#if !GCC_OLDER_THAN(5,0)
constexpr
#endif
static inline bool
audio_valid_sample_format(SampleFormat format)
{
switch (format) {
@@ -83,7 +86,10 @@ audio_valid_sample_format(SampleFormat format)
return false;
}
static constexpr inline unsigned
#if !GCC_OLDER_THAN(5,0)
constexpr
#endif
static inline unsigned
sample_format_size(SampleFormat format)
{
switch (format) {

View File

@@ -36,6 +36,7 @@
#include <type_traits>
#include <utility>
#include <new>
#include <cstdlib>
/**
* Allocate and construct a variable-size object. That is useful for