Skip to content
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

UCS/CONFIG/PARSER: Handle NULL entries in sparse arrays #10305

Draft
wants to merge 14 commits into
base: master
Choose a base branch
from

Conversation

michal-shalev
Copy link
Contributor

@michal-shalev michal-shalev commented Nov 15, 2024

What?

Following #10172

  • Changed parser.c to support sparse parsing of configuration environment variables.
  • Removed unnecessary flags from UCX_EXTRA_OP_ATTR_FLAGS.
  • Removed [*_LAST] = NULL null entries in configuration arrays.
  • Introduced UCS_CONFIG_DECLARE_ALLOWED_VALUES and UCS_CONFIG_DEFINE_ALLOWED_VALUES macros for cleaner handling of configuration arrays and their associated allowed values.
  • Added UCS_CONFIG_GET_ALLOWED_VALUES macro to retrieve allowed values consistently.
  • Changed UCS_CONFIG_TYPE_ENUM, UCS_CONFIG_TYPE_UINT_ENUM, and UCS_CONFIG_TYPE_BITMAP to work seamlessly with the new macros.

Why?

  • The previous implementation relied on the last entry in configuration arrays being NULL to determine the end of the array. This required unnecessary placeholder entries like [*_LAST] = NULL.
  • The previous implementation of UCS_CONFIG_TYPE_ENUM, UCS_CONFIG_TYPE_UINT_ENUM, and UCS_CONFIG_TYPE_BITMAP required contiguous indices, leading to core dumps when accessing NULL values due to gaps in the array.

How?

  • Introduced ucs_config_allowed_values_t to explicitly pass both the array pointer and the number of valid entries to the parser.
  • Updated parser.c to use the size specified in ucs_config_allowed_values_t instead of relying on NULL-terminated arrays.
  • Added the following macros:
    • UCS_CONFIG_DECLARE_ALLOWED_VALUES: For declaring allowed values arrays in headers when they are defined elsewhere.
    • UCS_CONFIG_DEFINE_ALLOWED_VALUES: For defining allowed values arrays in source files.
    • UCS_CONFIG_GET_ALLOWED_VALUES: For retrieving the allowed values object associated with an array.
  • Modified UCS_CONFIG_TYPE_ENUM, UCS_CONFIG_TYPE_UINT_ENUM, and UCS_CONFIG_TYPE_BITMAP to leverage the new macros and handle sparse arrays properly.

}

ret = 1;
*((uint64_t*)dest) = 0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would propose to create a variable to avoid repetitive casts:
uint64_t *flags = dest;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Outdated?


ret = 1;
*((uint64_t*)dest) = 0;
p = strtok_r(str, ",", &saveptr);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

consider using ucs_string_split

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Outdated?

Copy link
Contributor

@tvegas1 tvegas1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it possible to fix UCS_CONFIG_TYPE_BITMAP for sparse, instead of introducing new UCS_CONFIG_TYPE_FLAGS?

@michal-shalev
Copy link
Contributor Author

is it possible to fix UCS_CONFIG_TYPE_BITMAP for sparse, instead of introducing new UCS_CONFIG_TYPE_FLAGS?

@tvegas1
The alternative is to change UCS_CONFIG_TYPE_BITMAP instances unrelated to the flags, but it is not critical for me.

@yosefe
Copy link
Contributor

yosefe commented Nov 18, 2024

is it possible to fix UCS_CONFIG_TYPE_BITMAP for sparse, instead of introducing new UCS_CONFIG_TYPE_FLAGS?

We could do it nicely by adding another "unsigned long" field to ucs_config_parser_t to hold the count, something like

typedef struct ucs_config_parser {
    ...
    void                     (*help)(char *buf, size_t max, const void *arg);
    void                     (*doc)(ucs_string_buffer_t *strb, const void *arg);
    const void               *arg_ptr;
    unsigned long            arg_ulong;
};

And setting arg_ulong by ucs_static_array_size

@michal-shalev
Copy link
Contributor Author

michal-shalev commented Nov 18, 2024

is it possible to fix UCS_CONFIG_TYPE_BITMAP for sparse, instead of introducing new UCS_CONFIG_TYPE_FLAGS?

We could do it nicely by adding another "unsigned long" field to ucs_config_parser_t to hold the count, something like

typedef struct ucs_config_parser {
    ...
    void                     (*help)(char *buf, size_t max, const void *arg);
    void                     (*doc)(ucs_string_buffer_t *strb, const void *arg);
    const void               *arg_ptr;
    unsigned long            arg_ulong;
};

And setting arg_ulong by ucs_static_array_size

We could but it will require changes in all the parsers, which is more than the scope of the flags, LMK WDYT @yosefe

@yosefe
Copy link
Contributor

yosefe commented Nov 18, 2024

is it possible to fix UCS_CONFIG_TYPE_BITMAP for sparse, instead of introducing new UCS_CONFIG_TYPE_FLAGS?

We could do it nicely by adding another "unsigned long" field to ucs_config_parser_t to hold the count, something like

typedef struct ucs_config_parser {
    ...
    void                     (*help)(char *buf, size_t max, const void *arg);
    void                     (*doc)(ucs_string_buffer_t *strb, const void *arg);
    const void               *arg_ptr;
    unsigned long            arg_ulong;
};

And setting arg_ulong by ucs_static_array_size

We could but it will require changes in all the parsers, which is more than the scope of the flags, LMK WDYT @yosefe

I think it's worth it , but would appreciate @gleon99 @brminich @tvegas1 opinions

@tvegas1
Copy link
Contributor

tvegas1 commented Nov 20, 2024

We could but it will require changes in all the parsers, which is more than the scope of the flags, LMK WDYT @yosefe

I think it's worth it , but would appreciate @gleon99 @brminich @tvegas1 opinions

I would try to have only one UCS_CONFIG_TYPE_BITMAP that supports holes because _TYPE_FLAGS seems to be more or less the same, if that's possible.

@michal-shalev michal-shalev marked this pull request as draft December 2, 2024 20:50
@michal-shalev michal-shalev force-pushed the handle-null-entries-in-parser branch from 32b0d7b to 2a29c90 Compare December 11, 2024 21:53
@michal-shalev michal-shalev force-pushed the handle-null-entries-in-parser branch 6 times, most recently from f1bc871 to 836901c Compare January 7, 2025 13:50
@michal-shalev michal-shalev marked this pull request as ready for review January 7, 2025 14:58
#define UCS_CONFIG_TYPE_ENUM(allowed_values) {ucs_config_sscanf_enum, ucs_config_sprintf_enum, \
ucs_config_clone_uint, ucs_config_release_nop, \
ucs_config_help_enum, ucs_config_doc_nop, \
&UCS_CONFIG_ALLOWED_VALUES_NAME(allowed_values)}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can get rid of all DECLARE and DEFINE macros by using slightly more advanced macro here, with static initializer and compound literal:

#define UCS_CONFIG_TYPE_ENUM(t)    {ucs_config_sscanf_enum,      ucs_config_sprintf_enum, \
                                    ucs_config_clone_uint,       ucs_config_release_nop, \
                                    ucs_config_help_enum,        ucs_config_doc_nop, \
        (const ucs_config_allowed_values_t[]) { \
            { .values=t, .count = ucs_static_array_size(t)} \
        } \
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The proposed approach using will not work for cases where the array is declared as extern in a header file and defined elsewhere, which is common in our codebase.

For example, arrays like ucs_memory_type_names are declared as extern in the header file memory_type.h and defined in the source file memory_type.c.
When sizeof is used in a file where only the extern declaration is visible, the compiler treats the array as an incomplete type, resulting in the following error:
error: invalid application of ‘sizeof’ to incomplete type ‘const char *[]’

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I see
Maybe we declare these extern vars with array size?
E.g:

extern const char *ucm_mmap_hook_modes[UCM_MMAP_HOOK_LAST + 1];

@@ -66,7 +66,6 @@ typedef enum ucm_mmap_hook_mode {
UCM_MMAP_HOOK_NONE,
UCM_MMAP_HOOK_RELOC,
UCM_MMAP_HOOK_BISTRO,
UCM_MMAP_HOOK_LAST
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure we need to remove all those LAST fields. Does it harm if we keep them?
If not, I would keep them and reduce the PR size

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed the LAST fields that were no longer used anywhere and were not needed anymore

@michal-shalev michal-shalev force-pushed the handle-null-entries-in-parser branch from 836901c to a81e6b3 Compare January 9, 2025 09:59
@michal-shalev michal-shalev force-pushed the handle-null-entries-in-parser branch 3 times, most recently from aebd495 to 95e2f81 Compare January 9, 2025 17:19
@michal-shalev michal-shalev force-pushed the handle-null-entries-in-parser branch from 95e2f81 to 9a593fb Compare January 9, 2025 17:24
@michal-shalev michal-shalev force-pushed the handle-null-entries-in-parser branch from 27df86d to 18aca55 Compare January 11, 2025 14:21
@@ -542,7 +535,7 @@ static ucs_config_field_t ucp_context_config_table[] = {
{"EXTRA_OP_ATTR_FLAGS", "",
"Additional send/receive operation flags that are added for each request"
"in addition to what is set explicitly by the user. \n"
"Possible values are: no_imm_cmpl, fast_cmpl, force_imm_cmpl, multi_send.",
"Possible values are: fast_cmpl, multi_send.",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the line can be remove, it is already included in the help's output.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Other UCS_CONFIG_TYPE_BITMAP help messages in ucp_context_config_table show the options as well, see reg_whole_alloc_bitmap for example

Copy link
Contributor

@rakhmets rakhmets Mar 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean the same information is repeated twice in the output of ucx_info -cf:

# Additional send/receive operation flags that are added for each requestin addition to what is set explicitly by the user. 
# Possible values are: fast_cmpl, multi_send.
# 
#
# syntax:    comma-separated list of: [fast_cmpl|multi_send]

Some other messages have the same issue.

* UCS_CONFIG_DECLARE_ALLOWED_VALUES(ucm_log_level_names);
*/
#define UCS_CONFIG_DECLARE_ALLOWED_VALUES(_arr) \
extern const char *(_arr)[]; \
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can make it const char *const, since all related function signatures have been changed in the PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean in parser.h? const char *buf?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean it is not just an array of constant strings, but a constant-size array of constant strings.

@michal-shalev michal-shalev added WIP-DNM Work in progress / Do not review and removed Ready for Review labels Feb 24, 2025
@michal-shalev michal-shalev requested a review from rakhmets March 3, 2025 08:54
@michal-shalev
Copy link
Contributor Author

@gleon99 @iyastreb
After a discussion with @yosefe, he requested to move forward with this code by replacing the macro-based approach with a new data structure that maps numbers to strings. Since most arrays in the config parser are based on enums, this structure should also store the size, addressing both the sparse array issue and cases where different parts of the code need to retrieve a string based on an enum offset.
However, since this task is low priority, it will take some time before I get back to it. Moving this back to draft for now.

@michal-shalev michal-shalev marked this pull request as draft March 9, 2025 20:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
WIP-DNM Work in progress / Do not review
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants