mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-11-10 06:01:52 +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,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…
Reference in a new issue