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
13 changes: 6 additions & 7 deletions autotests/index/test_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,15 +83,14 @@ class PluginTest : public testing::Test
stub_ext::StubExt stub;
};

TEST_F(PluginTest, DSMRegister_ReturnsZero)
TEST_F(PluginTest, DSMRegister_ReturnsValidResult)
{
// DSMRegister creates DBus objects; should return 0
// DBus registration may fail in sandbox but the function
// should still return 0
// Returns 0 on success, -1 if DBus registration fails (e.g. in sandbox).
// Either way the function must not crash.
int result = anything_index::registerIndexServices();
EXPECT_EQ(result, 0);
EXPECT_TRUE(result == 0 || result == -1);

// Clean up via DSMUnRegister
// Clean up via DSMUnRegister (safe to call even if register failed)
anything_index::unregisterIndexServices();
}

Expand Down Expand Up @@ -125,6 +124,6 @@ TEST_F(PluginTest, DSMUnRegister_CalledTwice)
TEST_F(PluginTest, DSMRegister_WithNullName)
{
int result = anything_index::registerIndexServices();
EXPECT_EQ(result, 0);
EXPECT_TRUE(result == 0 || result == -1);
anything_index::unregisterIndexServices();
}
52 changes: 52 additions & 0 deletions src/index/dbus/filenameindexdbus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,32 @@
#include "utils/indexutility.h"
#include "utils/pinyinprocessor.h"

#include <QDir>

Check warning on line 11 in src/index/dbus/filenameindexdbus.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QDir> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QDBusConnection>

Check warning on line 12 in src/index/dbus/filenameindexdbus.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QDBusConnection> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QDebug>

Check warning on line 13 in src/index/dbus/filenameindexdbus.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QDebug> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QFile>

Check warning on line 14 in src/index/dbus/filenameindexdbus.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QFile> not found. Please note: Cppcheck does not need standard library headers to get proper results.

#include <fcntl.h>

Check warning on line 16 in src/index/dbus/filenameindexdbus.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <fcntl.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <unistd.h>

Check warning on line 17 in src/index/dbus/filenameindexdbus.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <unistd.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.

ANYTHING_INDEX_USE_NAMESPACE

namespace {

// Sentinel file used to detect abnormal service exit (SIGKILL, crash, OOM).
// Created at startup, removed during normal cleanup(). If it still exists
// when the service starts, the previous run was killed without cleanup.
inline constexpr char kSentinelFileName[] = ".filename_index_running";

QString sentinelFilePath(const QString &indexDir)
{
if (indexDir.isEmpty()) {
return QString();
}

return indexDir + QLatin1Char('/') + QLatin1String(kSentinelFileName);
}
Comment thread
sourcery-ai[bot] marked this conversation as resolved.

QStringList defaultPathsToProcess()
{
const auto &configuredDirs = DFMSEARCH::Global::defaultIndexedDirectory();
Expand Down Expand Up @@ -43,6 +61,32 @@
// time because the service process is always started fresh by the daemon.
runtime->fsEventController()->setSilentlyRefreshStarted(true);

// Sentinel file: detect abnormal exit from the previous run.
// On normal shutdown cleanup() removes the sentinel. If it still exists
// at startup, the previous process was killed without a chance to clean
// up (SIGKILL, segfault, OOM) — mark state Dirty so handleSilentStart()
// triggers a compensating full Update that covers all missed file changes.
const QString indexDir = runtime->profile().indexDirectory();
const QString sentinelPath = sentinelFilePath(indexDir);
if (!sentinelPath.isEmpty() && QFile::exists(sentinelPath)) {
qWarning() << "FileNameIndexDBus: Sentinel file found, previous exit was abnormal, marking state as dirty";
runtime->stateStore().setIndexState(IndexUtility::IndexState::Dirty);
}

// Create (or recreate) the sentinel file for this run.
// Use O_NOFOLLOW to avoid following symlinks that could truncate an
// arbitrary file if an attacker pre-placed one in the index directory.
if (!indexDir.isEmpty()) {
QDir().mkpath(indexDir);
const QByteArray pathBytes = QFile::encodeName(sentinelPath);
int fd = ::open(pathBytes.constData(), O_CREAT | O_WRONLY | O_NOFOLLOW | O_TRUNC, 0644);
if (fd >= 0) {
::close(fd);
} else {
qWarning() << "FileNameIndexDBus: Failed to create sentinel file:" << sentinelPath;
}
}

// Check for dirty state at startup and set recovery pending flag
// This must be done before any incremental task can complete and clear the Dirty state
const IndexUtility::IndexState state = runtime->stateStore().getIndexState();
Expand Down Expand Up @@ -209,6 +253,14 @@
}

StopCurrentTask();

// Remove sentinel file on normal exit so the next startup knows
// the previous shutdown was clean.
const QString indexDir = d->runtime->profile().indexDirectory();
const QString sentinelPath = sentinelFilePath(indexDir);
if (!sentinelPath.isEmpty() && QFile::exists(sentinelPath) && !QFile::remove(sentinelPath)) {
qWarning() << "FileNameIndexDBus: Failed to remove sentinel file:" << sentinelPath;
}
}

bool FileNameIndexDBus::IsEnabled()
Expand Down
5 changes: 4 additions & 1 deletion src/index/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,10 @@ int main(int argc, char *argv[])
QGuiApplication::setApplicationName("deepin-anything-index");
QGuiApplication::setApplicationVersion("1.0.0");

anything_index::registerIndexServices();
if (anything_index::registerIndexServices() != 0) {
qWarning() << "deepin-anything-index: failed to register DBus services, exiting";
return 1;
}

// Turn SIGTERM/SIGINT into a graceful shutdown (stop monitoring, stop the
// running task, mark unfinished indexes dirty, unregister bus names).
Expand Down
21 changes: 12 additions & 9 deletions src/index/serviceentry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,22 @@ int registerIndexServices()
qDBusRegisterMetaType<QHash<QString, QString>>();

QDBusConnection bus = QDBusConnection::sessionBus();
if (!bus.registerService(Defines::kTextIndexDBusService)
&& bus.lastError().type() != QDBusError::NoError) {
qWarning() << "deepin-anything-index: failed to register text index DBus service:" << bus.lastError().message();
if (!bus.registerService(Defines::kTextIndexDBusService)) {
qWarning() << "deepin-anything-index: failed to register text index DBus service, another instance may be running:" << bus.lastError().message();
return -1;
}

if (!bus.registerService(Defines::kOcrIndexDBusService)
&& bus.lastError().type() != QDBusError::NoError) {
qWarning() << "deepin-anything-index: failed to register OCR index DBus service:" << bus.lastError().message();
if (!bus.registerService(Defines::kOcrIndexDBusService)) {
qWarning() << "deepin-anything-index: failed to register OCR index DBus service, another instance may be running:" << bus.lastError().message();
bus.unregisterService(Defines::kTextIndexDBusService);
return -1;
}

if (!bus.registerService(Defines::kFileNameIndexDBusService)
&& bus.lastError().type() != QDBusError::NoError) {
qWarning() << "deepin-anything-index: failed to register filename index DBus service:" << bus.lastError().message();
if (!bus.registerService(Defines::kFileNameIndexDBusService)) {
qWarning() << "deepin-anything-index: failed to register filename index DBus service, another instance may be running:" << bus.lastError().message();
bus.unregisterService(Defines::kOcrIndexDBusService);
bus.unregisterService(Defines::kTextIndexDBusService);
return -1;
}

textIndexDBus = new TextIndexDBus();
Expand Down
2 changes: 1 addition & 1 deletion src/index/serviceentry.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace anything_index {

// Registers the three D-Bus service names (org.deepin.Filemanager.TextIndex /
// OcrIndex / FileNameIndex), creates the three D-Bus objects and lowers the
// process priority. Returns 0 on success, matching the old DSMRegister contract.
// process priority. Returns 0 on success, -1 if any DBus registration fails.
int registerIndexServices();

// Stops monitoring and running tasks, marks unfinished indexes dirty and
Expand Down
Loading