Skip to content

Commit

Permalink
Fix crash due to deadlocked mutex when holding keys
Browse files Browse the repository at this point in the history
  • Loading branch information
Brandon-T committed Sep 6, 2023
1 parent 111305b commit 745bb49
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 25 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,4 @@
*.exe
*.out
*.app
/cmake-build-*
4 changes: 2 additions & 2 deletions RemoteInput/Plugin/ControlCenter.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ void ControlCenter::process_command() noexcept
case EIOSCommand::IS_MOUSE_HELD:
{
std::int32_t button = stream.read<std::int32_t>();
jboolean result = io_controller->is_mouse_held(button);
bool result = io_controller->is_mouse_held(button);
stream.write(result);
}
break;
Expand Down Expand Up @@ -328,7 +328,7 @@ void ControlCenter::process_command() noexcept
case EIOSCommand::IS_KEY_HELD:
{
std::int32_t keycode = stream.read<std::int32_t>();
jboolean result = io_controller->is_key_held(keycode);
bool result = io_controller->is_key_held(keycode);
stream.write(result);
}
break;
Expand Down
44 changes: 24 additions & 20 deletions RemoteInput/Plugin/InputOutput.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -201,15 +201,15 @@ void InputOutput::hold_key(std::int32_t code) noexcept
}

//Key is not already held..
if (std::find(held_keys.begin(), held_keys.end(), code) == held_keys.end())
if (!this->is_key_held(code))
{
//Key is a control key
if (std::find(std::begin(control_keys), std::end(control_keys), code) != std::end(control_keys))
{
std::lock_guard<std::mutex> lock(this->mutex);

//Control Keys only generate a single held event..
this->mutex.lock();
held_keys.push_back(code);
this->mutex.unlock();

//PostEvent
java::Component receiver = control_center->reflect_canvas();
Expand Down Expand Up @@ -239,10 +239,10 @@ void InputOutput::hold_key(std::int32_t code) noexcept
//Key already being pressed so just replace it
if (currently_held_key != -1 && this->keyboard_speed >= 0 && this->keyboard_repeat_delay >= 0)
{
std::lock_guard<std::mutex> lock(this->mutex);

this->mutex.lock();
currently_held_key = code;
held_keys.push_back(code);
this->mutex.unlock();

//Post Event
java::Component receiver = control_center->reflect_canvas();
Expand Down Expand Up @@ -285,6 +285,7 @@ void InputOutput::hold_key(std::int32_t code) noexcept
this->mutex.lock();
currently_held_key = code;
held_keys.push_back(code);
this->mutex.unlock();

//Post Event
java::Component receiver = control_center->reflect_canvas();
Expand Down Expand Up @@ -316,7 +317,6 @@ void InputOutput::hold_key(std::int32_t code) noexcept
0,
NativeKeyCodeToChar(code, modifiers),
java::KeyEvent::KeyCodes::KEY_LOCATION_UNKNOWN);
this->mutex.unlock();

if (this->keyboard_speed >= 0 && this->keyboard_repeat_delay >= 0)
{
Expand All @@ -332,17 +332,16 @@ void InputOutput::hold_key(std::int32_t code) noexcept
java::Applet applet{env, this->applet, false};
java::Component receiver = applet.getComponent(0);

while (!stopped && currently_held_key != -1)
while (!stopped)
{
std::lock_guard<std::mutex> lock(this->mutex);
if (this->keyboard_speed > 0)
if (currently_held_key == -1)
{
yield_thread(std::chrono::milliseconds(this->keyboard_speed));
break;
}

if (currently_held_key == -1)
if (this->keyboard_speed > 0)
{
break;
yield_thread(std::chrono::milliseconds(this->keyboard_speed));
}

std::int32_t code = currently_held_key;
Expand Down Expand Up @@ -395,9 +394,9 @@ void InputOutput::release_key(std::int32_t code) noexcept
{
if (std::find(std::begin(control_keys), std::end(control_keys), code) != std::end(control_keys))
{
std::lock_guard<std::mutex> lock(this->mutex);

this->mutex.lock();
held_keys.erase(it); //held_keys.erase(std::remove(held_keys.begin(), held_keys.end(), code), held_keys.end());
this->mutex.unlock();

//Post Event
java::Component receiver = control_center->reflect_canvas();
Expand Down Expand Up @@ -437,7 +436,6 @@ void InputOutput::release_key(std::int32_t code) noexcept
this->mutex.unlock();

//Post Event
std::lock_guard<std::mutex> lock(this->mutex);
java::Component receiver = control_center->reflect_canvas();
if (!this->has_focus(&receiver))
{
Expand All @@ -462,16 +460,22 @@ void InputOutput::release_key(std::int32_t code) noexcept
}
}

bool InputOutput::is_key_held(std::int32_t code) const noexcept
bool InputOutput::is_key_held(std::int32_t code) noexcept
{
return std::find(std::begin(held_keys), std::end(held_keys), code) != std::end(held_keys);
this->mutex.lock();
bool result = std::find(std::begin(held_keys), std::end(held_keys), code) != std::end(held_keys);
this->mutex.unlock();
return result;
}

bool InputOutput::any_key_held(std::array<std::int32_t, 4>&& keys) const noexcept
bool InputOutput::any_key_held(std::array<std::int32_t, 4>&& keys) noexcept
{
return std::any_of(std::cbegin(held_keys), std::cend(held_keys), [&](std::int32_t key){
this->mutex.lock();
bool result = std::any_of(std::cbegin(held_keys), std::cend(held_keys), [&](std::int32_t key){
return std::find(std::cbegin(keys), std::cend(keys), key) != std::cend(keys);
});
this->mutex.unlock();
return result;
}

void InputOutput::send_string(std::string string, std::int32_t keywait, std::int32_t keymodwait) const noexcept
Expand Down Expand Up @@ -1189,7 +1193,7 @@ std::int32_t InputOutput::GetKeyLocation(std::int32_t keycode) const noexcept
return java::KeyEvent::KeyCodes::KEY_LOCATION_STANDARD;
}

std::int32_t InputOutput::GetActiveKeyModifiers() const noexcept
std::int32_t InputOutput::GetActiveKeyModifiers() noexcept
{
std::int32_t modifiers = 0;

Expand Down
6 changes: 3 additions & 3 deletions RemoteInput/Plugin/InputOutput.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,15 @@ private:
jchar NativeKeyCodeToChar(std::int32_t keycode, std::int32_t modifiers) const noexcept;
std::int32_t GetJavaKeyCode(std::int32_t native_key_code) const noexcept;
std::int32_t GetKeyLocation(std::int32_t keycode) const noexcept;
std::int32_t GetActiveKeyModifiers() const noexcept;
std::int32_t GetActiveKeyModifiers() noexcept;
std::int32_t ModifiersForChar(char c) const noexcept;
std::int32_t SimbaMouseButtonToJava(std::int32_t button) const noexcept;

bool has_focus(java::Component* component) const noexcept;
void gain_focus(java::Component* component) const noexcept;
void lose_focus(java::Component* component) const noexcept;

bool any_key_held(std::array<std::int32_t, 4>&& keys) const noexcept;
bool any_key_held(std::array<std::int32_t, 4>&& keys) noexcept;
void handle_resize(java::Component* component) noexcept;

public:
Expand All @@ -76,7 +76,7 @@ public:

void hold_key(std::int32_t code) noexcept;
void release_key(std::int32_t code) noexcept;
bool is_key_held(std::int32_t code) const noexcept;
bool is_key_held(std::int32_t code) noexcept;
void send_string(std::string string, std::int32_t keywait, std::int32_t keymodwait) const noexcept;

void get_mouse_position(std::int32_t* x, std::int32_t* y) noexcept;
Expand Down

0 comments on commit 745bb49

Please sign in to comment.