Skip to content

issue: 4432879 Refactor event_handler_manager #245

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: vNext
Choose a base branch
from

Conversation

pasis
Copy link
Member

@pasis pasis commented Oct 2, 2024

Description

Avoid start_thread with each reg action.
Refactor destructor.

What

Avoid start_thread with each reg action.
Refactor destructor.

Why ?

Potential CPU improvement for CPS and code cleanup.

Change type

What kind of change does this PR introduce?

  • Bugfix
  • Feature
  • Code style update
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • CI related changes
  • Documentation content changes
  • Tests
  • Other

Check list

  • Code follows the style de facto guidelines of this project
  • Comments have been inserted in hard to understand places
  • Documentation has been updated (if necessary)
  • Test has been added (if possible)

@pasis pasis added the draft Not to review yet label Oct 2, 2024
@galnoam
Copy link
Collaborator

galnoam commented Mar 16, 2025

@pasis, can we keep this in your privare fork?

@galnoam
Copy link
Collaborator

galnoam commented Mar 17, 2025

bot:retest

@galnoam galnoam removed the draft Not to review yet label Mar 17, 2025
pasis added 2 commits May 5, 2025 17:26
Event handler manager is a global object with a single internal thread.
Once XLIO is initialized, there is no option not to start the internal
thread and it's used starting from the initialization method (to create
a timer event for netlink).

Therefore, there is no point in trying to start the thread with each
post action to the event handler. This can save CPU in CPS scenario.

Signed-off-by: Dmytro Podgornyi <[email protected]>
This method simply calls stop_thread(). Remove it to simply the code and
separate thread stopping from epfd closing.

Signed-off-by: Dmytro Podgornyi <[email protected]>
@pasis pasis changed the title issue: Refactor event_handler_manager issue: 4432879 Refactor event_handler_manager May 5, 2025
@galnoam
Copy link
Collaborator

galnoam commented May 12, 2025

bot:retest

1 similar comment
@galnoam
Copy link
Collaborator

galnoam commented May 13, 2025

bot:retest

@galnoam
Copy link
Collaborator

galnoam commented May 14, 2025

/review

@galnoam
Copy link
Collaborator

galnoam commented May 14, 2025

/improve

Copy link

PR Reviewer Guide 🔍

Here are some key observations to aid the review process:

⏱️ Estimated effort to review: 4 🔵🔵🔵🔵⚪
🧪 No relevant tests
🔒 No security concerns identified
⚡ Recommended focus areas for review

Resource Cleanup

Ensure that the m_epfd resource is properly closed and reset in the destructor to avoid resource leaks or undefined behavior.

if (m_epfd >= 0) {
    SYSCALL(close, m_epfd);
}
m_epfd = -1;
Thread Affinity Handling

Validate the logic for setting thread affinity and fallback mechanisms in start_thread to ensure compatibility and robustness across different environments.

bool affinity_requested = false;

if (!m_b_continue_running) {
    errno = ECANCELED;
    return -1;
}
if (m_event_handler_tid != 0) {
    return 0;
}

ret = pthread_attr_init(&tattr);
if (ret != 0) {
    return -1;
}

cpu_set = safe_mce_sys().internal_thread_affinity;
if (strcmp(safe_mce_sys().internal_thread_affinity_str, "-1") &&
    !strcmp(safe_mce_sys().internal_thread_cpuset, MCE_DEFAULT_INTERNAL_THREAD_CPUSET)) {
    ret = pthread_attr_setaffinity_np(&tattr, sizeof(cpu_set), &cpu_set);
    if (ret != 0) {
        evh_logwarn("Failed to set event handler thread affinity. (errno=%d)", errno);
    }
    affinity_requested = (ret == 0);
} else {
    evh_logdbg("Internal thread affinity not set.");
}

ret = pthread_create(&m_event_handler_tid, &tattr, event_handler_thread, this);
if (ret != 0 && affinity_requested) {
    // Try without affinity in case this is a cset issue.
    evh_logwarn("Failed to start event handler thread with a thread affinity. Trying default "
                "thread affinity. (errno=%d)",
                errno);
    pthread_attr_destroy(&tattr);
    ret = pthread_attr_init(&tattr)
        ?: pthread_create(&m_event_handler_tid, &tattr, event_handler_thread, this);
}
// Destroy will either succeed or return EINVAL if the init fails in the above block.
pthread_attr_destroy(&tattr);

if (ret == 0) {
    evh_logdbg("Started event handler thread.");
} else {
    evh_logerr("Failed to start event handler thread. (errno=%d)", errno);
}
return ret;
Exception Handling

Confirm that throwing an exception when start_thread fails in do_global_ctors_helper is the appropriate behavior and won't cause unintended side effects during initialization.

if (rc != 0) {
    BULLSEYE_EXCLUDE_BLOCK_START
    throw_xlio_exception("Failed to start event handler thread.\n");
    BULLSEYE_EXCLUDE_BLOCK_END
}

Copy link

pr-review-bot-app bot commented May 14, 2025

PR Code Suggestions ✨

CategorySuggestion                                                                                                                                    Impact
Possible issue
Add error handling for thread initialization

Add error handling for the pthread_attr_init and pthread_create calls to ensure that
any failure in these operations is logged or handled appropriately, avoiding
potential undefined behavior.

src/core/event/event_handler_manager.cpp [347-348]

-ret = pthread_attr_init(&tattr)
-    ?: pthread_create(&m_event_handler_tid, &tattr, event_handler_thread, this);
+ret = pthread_attr_init(&tattr);
+if (ret != 0) {
+    evh_logerr("Failed to initialize thread attributes. (errno=%d)", errno);
+    return ret;
+}
+ret = pthread_create(&m_event_handler_tid, &tattr, event_handler_thread, this);
+if (ret != 0) {
+    evh_logerr("Failed to create event handler thread. (errno=%d)", errno);
+    pthread_attr_destroy(&tattr);
+    return ret;
+}
Suggestion importance[1-10]: 8

__

Why: The suggestion improves robustness by adding error handling for pthread_attr_init and pthread_create. This ensures that failures in thread initialization are logged and handled properly, reducing the risk of undefined behavior.

Medium
Add null check for pointer access

Add a null check for m_p_reg_action_q_to_push_to before accessing it to prevent
potential segmentation faults if the pointer is null.

src/core/event/event_handler_manager.cpp [446]

-is_empty = m_p_reg_action_q_to_push_to->empty();
+is_empty = (m_p_reg_action_q_to_push_to && m_p_reg_action_q_to_push_to->empty());
Suggestion importance[1-10]: 8

__

Why: Adding a null check for m_p_reg_action_q_to_push_to prevents potential segmentation faults, which is a significant improvement for code safety and stability.

Medium
Prevent resource leaks in thread attributes

Ensure that the pthread_attr_destroy is called after the second pthread_attr_init to
avoid resource leaks in case of repeated initialization.

src/core/event/event_handler_manager.cpp [341-349]

 if (ret != 0 && affinity_requested) {
     evh_logwarn("Failed to start event handler thread with a thread affinity. Trying default "
                 "thread affinity. (errno=%d)",
                 errno);
     pthread_attr_destroy(&tattr);
-    ret = pthread_attr_init(&tattr)
-        ?: pthread_create(&m_event_handler_tid, &tattr, event_handler_thread, this);
+    ret = pthread_attr_init(&tattr);
+    if (ret == 0) {
+        ret = pthread_create(&m_event_handler_tid, &tattr, event_handler_thread, this);
+        pthread_attr_destroy(&tattr);
+    }
 }
Suggestion importance[1-10]: 7

__

Why: The suggestion ensures that pthread_attr_destroy is called after the second pthread_attr_init, preventing resource leaks. This is a good improvement for resource management and aligns with best practices.

Medium
General
Log error code before exception

Log the error code before throwing the exception to provide more context for
debugging failures in starting the event handler thread.

src/core/main.cpp [1000-1003]

 rc = g_p_event_handler_manager->start_thread();
 if (rc != 0) {
+    evh_logerr("Failed to start event handler thread. (rc=%d)", rc);
     BULLSEYE_EXCLUDE_BLOCK_START
     throw_xlio_exception("Failed to start event handler thread.\n");
     BULLSEYE_EXCLUDE_BLOCK_END
 }
Suggestion importance[1-10]: 6

__

Why: Logging the error code before throwing an exception provides valuable debugging information. While not critical, it enhances the ability to diagnose issues when the thread fails to start.

Low

@galnoam
Copy link
Collaborator

galnoam commented May 14, 2025

Hi @pasis , @AlexanderGrissik , please check pr agent review comments.

@galnoam galnoam requested a review from AlexanderGrissik May 14, 2025 16:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants