mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2025-04-22 12:34:47 +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
f9a199557c
commit
c5bc7e7224
1 changed files with 37 additions and 12 deletions
|
@ -28,15 +28,41 @@ namespace ams::ldr::ecs {
|
|||
NON_COPYABLE(ExternalContentSource);
|
||||
NON_MOVEABLE(ExternalContentSource);
|
||||
private:
|
||||
bool has_mounted = false;
|
||||
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:
|
||||
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));
|
||||
this->device_name[sizeof(this->device_name) - 1] = '\0';
|
||||
}
|
||||
|
||||
Result EnsureMounted() {
|
||||
if (!this->has_mounted) {
|
||||
return Mount();
|
||||
}
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
~ExternalContentSource() {
|
||||
fsdevUnmountDevice(this->device_name);
|
||||
if (this->has_mounted) {
|
||||
fsdevUnmountDevice(this->device_name);
|
||||
}
|
||||
}
|
||||
|
||||
const char *GetDeviceName() const {
|
||||
|
@ -54,6 +80,10 @@ namespace ams::ldr::ecs {
|
|||
if (it == g_map.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
if (R_FAILED(it->second.EnsureMounted())) {
|
||||
g_map.erase(it);
|
||||
return nullptr;
|
||||
}
|
||||
return it->second.GetDeviceName();
|
||||
}
|
||||
|
||||
|
@ -72,18 +102,13 @@ namespace ams::ldr::ecs {
|
|||
os::ManagedHandle server, client;
|
||||
R_TRY(svcCreateSession(server.GetPointer(), client.GetPointer(), 0, 0));
|
||||
|
||||
/* 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();
|
||||
/* Do not create service yet. */
|
||||
/* Defer until we've handed the server side back so we don't deadlock on querying pointer buffer size. */
|
||||
|
||||
/* 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();
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue