mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-12-22 20:31:14 +00:00
loader: fix ECS after new-ipc rewrite
The call to serviceCreate(...) tries to query pointer buffer size, but since we haven't had a chance to return the server side of the session yet, this deadlocks. Instead, we defer creating the session and mounting the filesystem until the first time the ECS object is used. If mounting the filesystem fails, the ECS is silently discarded.
This commit is contained in:
parent
0a18c63f24
commit
f1a9dd8a98
1 changed files with 37 additions and 12 deletions
|
@ -28,16 +28,42 @@ namespace ams::ldr::ecs {
|
||||||
NON_COPYABLE(ExternalContentSource);
|
NON_COPYABLE(ExternalContentSource);
|
||||||
NON_MOVEABLE(ExternalContentSource);
|
NON_MOVEABLE(ExternalContentSource);
|
||||||
private:
|
private:
|
||||||
|
bool has_mounted = false;
|
||||||
char device_name[DeviceNameSizeMax];
|
char device_name[DeviceNameSizeMax];
|
||||||
|
os::ManagedHandle client;
|
||||||
|
|
||||||
|
Result Mount() {
|
||||||
|
/* Create service. */
|
||||||
|
Service srv;
|
||||||
|
serviceCreate(&srv, client.Move());
|
||||||
|
FsFileSystem fs = { srv };
|
||||||
|
auto fs_guard = SCOPE_GUARD { fsFsClose(&fs); };
|
||||||
|
|
||||||
|
/* Try to mount. */
|
||||||
|
R_UNLESS(fsdevMountDevice(device_name, fs) >= 0, fs::ResultMountNameAlreadyExists());
|
||||||
|
fs_guard.Cancel();
|
||||||
|
|
||||||
|
this->has_mounted = true;
|
||||||
|
return ResultSuccess();
|
||||||
|
}
|
||||||
public:
|
public:
|
||||||
ExternalContentSource(const char *dn) {
|
ExternalContentSource(const char *dn, os::ManagedHandle client) : client(std::move(client)) {
|
||||||
std::strncpy(this->device_name, dn, sizeof(this->device_name));
|
std::strncpy(this->device_name, dn, sizeof(this->device_name));
|
||||||
this->device_name[sizeof(this->device_name) - 1] = '\0';
|
this->device_name[sizeof(this->device_name) - 1] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result EnsureMounted() {
|
||||||
|
if (!this->has_mounted) {
|
||||||
|
return Mount();
|
||||||
|
}
|
||||||
|
return ResultSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
~ExternalContentSource() {
|
~ExternalContentSource() {
|
||||||
|
if (this->has_mounted) {
|
||||||
fsdevUnmountDevice(this->device_name);
|
fsdevUnmountDevice(this->device_name);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const char *GetDeviceName() const {
|
const char *GetDeviceName() const {
|
||||||
return this->device_name;
|
return this->device_name;
|
||||||
|
@ -54,6 +80,10 @@ namespace ams::ldr::ecs {
|
||||||
if (it == g_map.end()) {
|
if (it == g_map.end()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
if (R_FAILED(it->second.EnsureMounted())) {
|
||||||
|
g_map.erase(it);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
return it->second.GetDeviceName();
|
return it->second.GetDeviceName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,18 +102,13 @@ namespace ams::ldr::ecs {
|
||||||
os::ManagedHandle server, client;
|
os::ManagedHandle server, client;
|
||||||
R_TRY(svcCreateSession(server.GetPointer(), client.GetPointer(), 0, 0));
|
R_TRY(svcCreateSession(server.GetPointer(), client.GetPointer(), 0, 0));
|
||||||
|
|
||||||
/* Create service. */
|
/* Do not create service yet. */
|
||||||
Service srv;
|
/* Defer until we've handed the server side back so we don't deadlock on querying pointer buffer size. */
|
||||||
serviceCreate(&srv, client.Move());
|
|
||||||
FsFileSystem fs = { srv };
|
|
||||||
auto fs_guard = SCOPE_GUARD { fsFsClose(&fs); };
|
|
||||||
|
|
||||||
/* Try to mount. */
|
|
||||||
R_UNLESS(fsdevMountDevice(device_name, fs) >= 0, fs::ResultMountNameAlreadyExists());
|
|
||||||
fs_guard.Cancel();
|
|
||||||
|
|
||||||
/* Add to map. */
|
/* Add to map. */
|
||||||
g_map.emplace(static_cast<u64>(program_id), device_name);
|
g_map.emplace(std::piecewise_construct,
|
||||||
|
std::make_tuple(static_cast<u64>(program_id)),
|
||||||
|
std::make_tuple(device_name, std::move(client)));
|
||||||
*out = server.Move();
|
*out = server.Move();
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue