mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2025-09-25 21:03:18 +02:00
haze: tear down sessions on suspension
This commit is contained in:
parent
a1175feab1
commit
d0364c31cc
@ -45,12 +45,16 @@ namespace haze {
|
|||||||
int idx;
|
int idx;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
|
/* Wait for up to 1 frame delay time to be cancelled. */
|
||||||
Waiter cancel_waiter = waiterForUEvent(std::addressof(m_cancel_event));
|
Waiter cancel_waiter = waiterForUEvent(std::addressof(m_cancel_event));
|
||||||
Result rc = waitObjects(std::addressof(idx), std::addressof(cancel_waiter), 1, FrameDelayNs);
|
Result rc = waitObjects(std::addressof(idx), std::addressof(cancel_waiter), 1, FrameDelayNs);
|
||||||
|
|
||||||
|
/* Finish if we were cancelled. */
|
||||||
if (R_SUCCEEDED(rc)) {
|
if (R_SUCCEEDED(rc)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Otherwise, signal the console update event. */
|
||||||
if (svc::ResultTimedOut::Includes(rc)) {
|
if (svc::ResultTimedOut::Includes(rc)) {
|
||||||
ueventSignal(std::addressof(m_event));
|
ueventSignal(std::addressof(m_event));
|
||||||
}
|
}
|
||||||
@ -154,13 +158,91 @@ namespace haze {
|
|||||||
|
|
||||||
/* If the plus button is held, request immediate exit. */
|
/* If the plus button is held, request immediate exit. */
|
||||||
if (padGetButtonsDown(std::addressof(m_pad)) & HidNpadButton_Plus) {
|
if (padGetButtonsDown(std::addressof(m_pad)) & HidNpadButton_Plus) {
|
||||||
m_reactor->RequestStop();
|
m_reactor->SetResult(haze::ResultStopRequested());
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Pump applet event loop. */
|
/* Pump applet events, and check if exit was requested. */
|
||||||
if (!appletMainLoop()) {
|
if (!appletMainLoop()) {
|
||||||
m_reactor->RequestStop();
|
m_reactor->SetResult(haze::ResultStopRequested());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check if focus was lost. */
|
||||||
|
if (appletGetFocusState() == AppletFocusState_Background) {
|
||||||
|
m_reactor->SetResult(haze::ResultFocusLost());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
static bool SuspendAndWaitForFocus() {
|
||||||
|
/* Enable suspension with resume notification. */
|
||||||
|
appletSetFocusHandlingMode(AppletFocusHandlingMode_SuspendHomeSleepNotify);
|
||||||
|
|
||||||
|
/* Pump applet events. */
|
||||||
|
while (appletMainLoop()) {
|
||||||
|
/* Check if focus was regained. */
|
||||||
|
if (appletGetFocusState() != AppletFocusState_Background) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Exit was requested. */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
static void RunApplication() {
|
||||||
|
/* Declare the object heap, to hold the database for an active session. */
|
||||||
|
PtpObjectHeap ptp_object_heap;
|
||||||
|
|
||||||
|
/* Declare the event reactor, and components which use it. */
|
||||||
|
EventReactor event_reactor;
|
||||||
|
PtpResponder ptp_responder;
|
||||||
|
ConsoleMainLoop console_main_loop;
|
||||||
|
|
||||||
|
/* Initialize the console.*/
|
||||||
|
consoleInit(nullptr);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
/* Disable suspension. */
|
||||||
|
appletSetFocusHandlingMode(AppletFocusHandlingMode_NoSuspend);
|
||||||
|
|
||||||
|
/* Declare result from serving to use. */
|
||||||
|
Result rc;
|
||||||
|
{
|
||||||
|
/* Ensure we don't go to sleep while transferring files. */
|
||||||
|
appletSetAutoSleepDisabled(true);
|
||||||
|
|
||||||
|
/* Clear the event reactor. */
|
||||||
|
event_reactor.SetResult(ResultSuccess());
|
||||||
|
|
||||||
|
/* Configure the PTP responder and console main loop. */
|
||||||
|
ptp_responder.Initialize(std::addressof(event_reactor), std::addressof(ptp_object_heap));
|
||||||
|
console_main_loop.Initialize(std::addressof(event_reactor), std::addressof(ptp_object_heap));
|
||||||
|
|
||||||
|
/* Ensure we maintain a clean state on exit. */
|
||||||
|
ON_SCOPE_EXIT {
|
||||||
|
/* Finalize the console main loop and PTP responder. */
|
||||||
|
console_main_loop.Finalize();
|
||||||
|
ptp_responder.Finalize();
|
||||||
|
|
||||||
|
/* Restore auto sleep setting. */
|
||||||
|
appletSetAutoSleepDisabled(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Begin processing requests. */
|
||||||
|
rc = ptp_responder.LoopProcess();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If focus was lost, try to pump the applet main loop until we receive focus again. */
|
||||||
|
if (haze::ResultFocusLost::Includes(rc) && SuspendAndWaitForFocus()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Otherwise, enable suspension and finish. */
|
||||||
|
appletSetFocusHandlingMode(AppletFocusHandlingMode_SuspendHomeSleep);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Finalize the console. */
|
||||||
|
consoleExit(nullptr);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -30,15 +30,15 @@ namespace haze {
|
|||||||
EventConsumer *m_consumers[svc::ArgumentHandleCountMax];
|
EventConsumer *m_consumers[svc::ArgumentHandleCountMax];
|
||||||
Waiter m_waiters[svc::ArgumentHandleCountMax];
|
Waiter m_waiters[svc::ArgumentHandleCountMax];
|
||||||
s32 m_num_wait_objects;
|
s32 m_num_wait_objects;
|
||||||
bool m_stop_requested;
|
Result m_result;
|
||||||
public:
|
public:
|
||||||
constexpr explicit EventReactor() : m_consumers(), m_waiters(), m_num_wait_objects(), m_stop_requested() { /* ... */ }
|
constexpr explicit EventReactor() : m_consumers(), m_waiters(), m_num_wait_objects(), m_result(ResultSuccess()) { /* ... */ }
|
||||||
|
|
||||||
bool AddConsumer(EventConsumer *consumer, Waiter waiter);
|
bool AddConsumer(EventConsumer *consumer, Waiter waiter);
|
||||||
void RemoveConsumer(EventConsumer *consumer);
|
void RemoveConsumer(EventConsumer *consumer);
|
||||||
public:
|
public:
|
||||||
void RequestStop() { m_stop_requested = true; }
|
void SetResult(Result r) { m_result = r; }
|
||||||
bool GetStopRequested() const { return m_stop_requested; }
|
Result GetResult() const { return m_result; }
|
||||||
public:
|
public:
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
Result WaitFor(s32 *out_arg_waiter, Args &&... arg_waiters) {
|
Result WaitFor(s32 *out_arg_waiter, Args &&... arg_waiters) {
|
||||||
|
@ -45,7 +45,7 @@ namespace haze {
|
|||||||
const Result rc = func(std::forward<Args>(args)...);
|
const Result rc = func(std::forward<Args>(args)...);
|
||||||
|
|
||||||
/* If the event loop was stopped, return that here. */
|
/* If the event loop was stopped, return that here. */
|
||||||
R_UNLESS(!m_reactor->GetStopRequested(), haze::ResultStopRequested());
|
R_TRY(m_reactor->GetResult());
|
||||||
|
|
||||||
/* Otherwise, return the call result. */
|
/* Otherwise, return the call result. */
|
||||||
R_RETURN(rc);
|
R_RETURN(rc);
|
||||||
|
@ -40,9 +40,10 @@ namespace haze {
|
|||||||
Result Initialize(EventReactor *reactor, PtpObjectHeap *object_heap);
|
Result Initialize(EventReactor *reactor, PtpObjectHeap *object_heap);
|
||||||
void Finalize();
|
void Finalize();
|
||||||
public:
|
public:
|
||||||
Result HandleRequest();
|
Result LoopProcess();
|
||||||
private:
|
private:
|
||||||
/* Request handling. */
|
/* Request handling. */
|
||||||
|
Result HandleRequest();
|
||||||
Result HandleRequestImpl();
|
Result HandleRequestImpl();
|
||||||
Result HandleCommandRequest(PtpDataParser &dp);
|
Result HandleCommandRequest(PtpDataParser &dp);
|
||||||
void ForceCloseSession();
|
void ForceCloseSession();
|
||||||
|
@ -26,16 +26,16 @@ namespace haze {
|
|||||||
R_DEFINE_ERROR_RESULT(NotConfigured, 2);
|
R_DEFINE_ERROR_RESULT(NotConfigured, 2);
|
||||||
R_DEFINE_ERROR_RESULT(TransferFailed, 3);
|
R_DEFINE_ERROR_RESULT(TransferFailed, 3);
|
||||||
R_DEFINE_ERROR_RESULT(StopRequested, 4);
|
R_DEFINE_ERROR_RESULT(StopRequested, 4);
|
||||||
R_DEFINE_ERROR_RESULT(EndOfTransmission, 5);
|
R_DEFINE_ERROR_RESULT(FocusLost, 5);
|
||||||
R_DEFINE_ERROR_RESULT(UnknownPacketType, 6);
|
R_DEFINE_ERROR_RESULT(EndOfTransmission, 6);
|
||||||
R_DEFINE_ERROR_RESULT(SessionNotOpen, 7);
|
R_DEFINE_ERROR_RESULT(UnknownPacketType, 7);
|
||||||
R_DEFINE_ERROR_RESULT(OutOfMemory, 8);
|
R_DEFINE_ERROR_RESULT(SessionNotOpen, 8);
|
||||||
R_DEFINE_ERROR_RESULT(InvalidObjectId, 9);
|
R_DEFINE_ERROR_RESULT(OutOfMemory, 9);
|
||||||
R_DEFINE_ERROR_RESULT(InvalidStorageId, 10);
|
R_DEFINE_ERROR_RESULT(InvalidObjectId, 10);
|
||||||
R_DEFINE_ERROR_RESULT(OperationNotSupported, 11);
|
R_DEFINE_ERROR_RESULT(InvalidStorageId, 11);
|
||||||
R_DEFINE_ERROR_RESULT(UnknownRequestType, 12);
|
R_DEFINE_ERROR_RESULT(OperationNotSupported, 12);
|
||||||
R_DEFINE_ERROR_RESULT(UnknownPropertyCode, 13);
|
R_DEFINE_ERROR_RESULT(UnknownRequestType, 13);
|
||||||
R_DEFINE_ERROR_RESULT(InvalidPropertyValue, 14);
|
R_DEFINE_ERROR_RESULT(UnknownPropertyCode, 14);
|
||||||
R_DEFINE_ERROR_RESULT(GeneralFailure, 15);
|
R_DEFINE_ERROR_RESULT(InvalidPropertyValue, 15);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ namespace haze {
|
|||||||
HAZE_ASSERT(m_num_wait_objects + num_arg_waiters <= svc::ArgumentHandleCountMax);
|
HAZE_ASSERT(m_num_wait_objects + num_arg_waiters <= svc::ArgumentHandleCountMax);
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
R_UNLESS(!m_stop_requested, haze::ResultStopRequested());
|
R_TRY(m_result);
|
||||||
|
|
||||||
/* Insert waiters from argument list. */
|
/* Insert waiters from argument list. */
|
||||||
for (s32 i = 0; i < num_arg_waiters; i++) {
|
for (s32 i = 0; i < num_arg_waiters; i++) {
|
||||||
|
@ -17,38 +17,8 @@
|
|||||||
#include <haze/console_main_loop.hpp>
|
#include <haze/console_main_loop.hpp>
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
/* Declare the object heap, to hold the database for an active session. */
|
/* Run the application. */
|
||||||
haze::PtpObjectHeap ptp_object_heap;
|
haze::ConsoleMainLoop::RunApplication();
|
||||||
|
|
||||||
/* Declare the event reactor, and components which use it. */
|
|
||||||
haze::EventReactor event_reactor;
|
|
||||||
haze::PtpResponder ptp_responder;
|
|
||||||
haze::ConsoleMainLoop console_main_loop;
|
|
||||||
|
|
||||||
/* Initialize the console.*/
|
|
||||||
consoleInit(nullptr);
|
|
||||||
|
|
||||||
/* Ensure we don't go to sleep while transferring files. */
|
|
||||||
appletSetAutoSleepDisabled(true);
|
|
||||||
|
|
||||||
/* Configure the PTP responder and console main loop. */
|
|
||||||
ptp_responder.Initialize(std::addressof(event_reactor), std::addressof(ptp_object_heap));
|
|
||||||
console_main_loop.Initialize(std::addressof(event_reactor), std::addressof(ptp_object_heap));
|
|
||||||
|
|
||||||
/* Process events until the user requests exit. */
|
|
||||||
while (!event_reactor.GetStopRequested()) {
|
|
||||||
ptp_responder.HandleRequest();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Finalize the console main loop and PTP responder. */
|
|
||||||
console_main_loop.Finalize();
|
|
||||||
ptp_responder.Finalize();
|
|
||||||
|
|
||||||
/* Restore auto sleep setting. */
|
|
||||||
appletSetAutoSleepDisabled(false);
|
|
||||||
|
|
||||||
/* Finalize the console. */
|
|
||||||
consoleExit(nullptr);
|
|
||||||
|
|
||||||
/* Return to the loader. */
|
/* Return to the loader. */
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -191,6 +191,25 @@ namespace haze {
|
|||||||
m_fs.Finalize();
|
m_fs.Finalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result PtpResponder::LoopProcess() {
|
||||||
|
while (true) {
|
||||||
|
/* Try to handle a request. */
|
||||||
|
R_TRY_CATCH(this->HandleRequest()) {
|
||||||
|
R_CATCH(haze::ResultStopRequested, haze::ResultFocusLost) {
|
||||||
|
/* If we encountered a stop condition, we're done.*/
|
||||||
|
R_THROW(R_CURRENT_RESULT);
|
||||||
|
}
|
||||||
|
R_CATCH_ALL() {
|
||||||
|
/* On other failures, try to handle another request. */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} R_END_TRY_CATCH;
|
||||||
|
|
||||||
|
/* Otherwise, handle the next request. */
|
||||||
|
/* ... */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Result PtpResponder::HandleRequest() {
|
Result PtpResponder::HandleRequest() {
|
||||||
ON_RESULT_FAILURE {
|
ON_RESULT_FAILURE {
|
||||||
/* For general failure modes, the failure is unrecoverable. Close the session. */
|
/* For general failure modes, the failure is unrecoverable. Close the session. */
|
||||||
@ -223,9 +242,6 @@ namespace haze {
|
|||||||
/* Errors from fs are typically recoverable. */
|
/* Errors from fs are typically recoverable. */
|
||||||
R_TRY(this->WriteResponse(PtpResponseCode_GeneralError));
|
R_TRY(this->WriteResponse(PtpResponseCode_GeneralError));
|
||||||
}
|
}
|
||||||
R_CATCH_ALL() {
|
|
||||||
R_THROW(haze::ResultGeneralFailure());
|
|
||||||
}
|
|
||||||
} R_END_TRY_CATCH;
|
} R_END_TRY_CATCH;
|
||||||
|
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
|
Loading…
Reference in New Issue
Block a user