Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,14 @@ ver 0.25 (not yet released)
* switch to C++23
* require Meson 1.2

ver 0.24.9 (not yet released)
ver 0.24.9 (2026/03/11)
* input
- curl: fix build failure after CURL 8.19 API change
* output
- fix auto-reopen after error times out
* database
- upnp: refuse to build with libupnp >= 1.14.26 due to API breakage
* abort if threads were created by a library during process startup

ver 0.24.8 (2026/01/26)
* input
Expand Down
10 changes: 10 additions & 0 deletions doc/developer.rst
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,16 @@ Some example code:
}


C++ Subset
==========

The following C++ features are not allowed in MPD:

* :code:`<filesystem>` (bloated)
* :code:`<iostream>` (bloated, weird error handling)
* :code:`<regex>` (PCRE is better)


Error handling
==============

Expand Down
2 changes: 2 additions & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,7 @@ subdir('src/cmdline')
subdir('src/time')
subdir('src/lib/icu')
subdir('src/io')
subdir('src/io/linux')
subdir('src/fs')
subdir('src/io/fs')
subdir('src/io/uring')
Expand Down Expand Up @@ -625,6 +626,7 @@ mpd = build_target(
fs_dep,
net_dep,
util_dep,
io_linux_dep,
event_dep,
thread_dep,
neighbor_glue_dep,
Expand Down
13 changes: 13 additions & 0 deletions src/Main.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@
#include "config/PartitionConfig.hxx"
#include "util/ScopeExit.hxx"

#ifdef __linux__
#include "io/linux/ProcStatus.hxx"
#endif

#ifdef ENABLE_DAEMON
#include "unix/Daemon.hxx"
#endif
Expand Down Expand Up @@ -693,6 +697,15 @@ mpd_main(int argc, char *argv[])
int
main(int argc, char *argv[]) noexcept
try {
#ifdef __linux__
if (ProcStatusThreads() > 1)
/* threads created by libraries before main() can
cause all sorts of bugs that are difficult to
analyze; bail out quickly and refuse to run if we
detect such a thing */
throw "Background threads were detected before MPD could initialize. This is likely caused by a misbehaving library. Aborting to prevent erroneous behavior. Please report.";
#endif

AtScopeExit() { log_deinit(); };

#ifdef _WIN32
Expand Down
8 changes: 3 additions & 5 deletions src/decoder/plugins/SidplayDecoderPlugin.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "util/AllocatedString.hxx"
#include "util/CharUtil.hxx"
#include "util/ByteOrder.hxx"
#include "util/StringCompare.hxx"
#include "Log.hxx"

#include <sidplayfp/sidplayfp.h>
Expand All @@ -34,8 +35,6 @@
#include <iterator>
#include <memory>

#include <string.h>

#define SUBTUNE_PREFIX "tune_"

static constexpr Domain sidplay_domain("sidplay");
Expand Down Expand Up @@ -136,11 +135,10 @@ struct SidplayContainerPath {
static unsigned
ParseSubtuneName(const char *base) noexcept
{
if (memcmp(base, SUBTUNE_PREFIX, sizeof(SUBTUNE_PREFIX) - 1) != 0)
base = StringAfterPrefix(base, SUBTUNE_PREFIX);
if (base == nullptr)
return 0;

base += sizeof(SUBTUNE_PREFIX) - 1;

char *endptr;
auto track = strtoul(base, &endptr, 10);
if (endptr == base || *endptr != '.')
Expand Down
36 changes: 36 additions & 0 deletions src/io/linux/ProcStatus.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// SPDX-License-Identifier: BSD-2-Clause
// author: Max Kellermann <max.kellermann@gmail.com>

#include "ProcStatus.hxx"
#include "io/UniqueFileDescriptor.hxx"
#include "util/NumberParser.hxx"
#include "util/StringSplit.hxx"

using std::string_view_literals::operator""sv;

unsigned
ProcStatusThreads() noexcept
{
UniqueFileDescriptor fd;
if (!fd.OpenReadOnly("/proc/self/status"))
return 0;

char buffer[4096];
ssize_t nbytes = fd.Read(std::as_writable_bytes(std::span{buffer}));
if (nbytes <= 0)
return 0;

const std::string_view contents{buffer, static_cast<std::size_t>(nbytes)};

static constexpr std::string_view prefix = "\nThreads:\t"sv;
const auto position = contents.find(prefix);
if (position == contents.npos)
return 0;

const std::string_view value_string = Split(contents.substr(position + prefix.size()), '\n').first;
unsigned value;
if (!ParseIntegerTo(value_string, value))
return 0;

return value;
}
13 changes: 13 additions & 0 deletions src/io/linux/ProcStatus.hxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// SPDX-License-Identifier: BSD-2-Clause
// author: Max Kellermann <max.kellermann@gmail.com>

#pragma once

/**
* Attempt to determine the number of threads of the current process.
*
* @return the number of threads or 0 on error
*/
[[gnu::pure]]
unsigned
ProcStatusThreads() noexcept;
23 changes: 23 additions & 0 deletions src/io/linux/meson.build
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
if not is_linux
io_linux_dep = dependency('', required: false)
subdir_done()
endif

io_linux = static_library(
'io_linux',
'ProcStatus.cxx',
include_directories: inc,
dependencies: [
io_dep,
util_dep,
],
)

io_linux_dep = declare_dependency(
link_with: io_linux,
dependencies: [
fmt_dep,
io_dep,
util_dep,
],
)
2 changes: 1 addition & 1 deletion src/output/Control.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ AudioOutputControl::LockUpdate(const AudioFormat audio_format,

if (enabled && really_enabled) {
if (force || !fail_timer.IsDefined() ||
fail_timer.Check(REOPEN_AFTER * 1000)) {
fail_timer.Check(REOPEN_AFTER)) {
return Open(std::move(lock), audio_format, mp);
}
} else if (IsOpen())
Expand Down
20 changes: 10 additions & 10 deletions subprojects/sqlite3.wrap
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
[wrap-file]
directory = sqlite-amalgamation-3510200
source_url = https://www.sqlite.org/2026/sqlite-amalgamation-3510200.zip
source_filename = sqlite-amalgamation-3510200.zip
source_hash = 6e2a845a493026bdbad0618b2b5a0cf48584faab47384480ed9f592d912f23ec
source_fallback_url = https://wrapdb.mesonbuild.com/v2/sqlite3_3.51.2-1/get_source/sqlite-amalgamation-3510200.zip
patch_filename = sqlite3_3.51.2-1_patch.zip
patch_url = https://wrapdb.mesonbuild.com/v2/sqlite3_3.51.2-1/get_patch
patch_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/sqlite3_3.51.2-1/sqlite3_3.51.2-1_patch.zip
patch_hash = eef624e9916ec7b7c62dccbf1a04a8bc6fdcacfb5b58daaba695c204e00bec67
wrapdb_version = 3.51.2-1
directory = sqlite-amalgamation-3520000
source_url = https://www.sqlite.org/2026/sqlite-amalgamation-3520000.zip
source_filename = sqlite-amalgamation-3520000.zip
source_hash = 45d0fea15971dd1300e5b509f48ca134621e10d9297713b64618fbca21b325fa
source_fallback_url = https://wrapdb.mesonbuild.com/v2/sqlite3_3.52.0-1/get_source/sqlite-amalgamation-3520000.zip
patch_filename = sqlite3_3.52.0-1_patch.zip
patch_url = https://wrapdb.mesonbuild.com/v2/sqlite3_3.52.0-1/get_patch
patch_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/sqlite3_3.52.0-1/sqlite3_3.52.0-1_patch.zip
patch_hash = a4b065e5bf76df313759c95aba623456744953b432b68e0c76f87b16d839293b
wrapdb_version = 3.52.0-1

[provide]
dependency_names = sqlite3
Loading