Skip to content

Commit dbf8d65

Browse files
committed
Update the sdk bootstrap code to fail fast on clear problems with the lib from alfasim
The problems covered in this update: - Can not load the lib (not found or corrupted); - Can not fetch the address of a function from the lib; ASIM-5532
1 parent 1214f36 commit dbf8d65

File tree

3 files changed

+136
-92
lines changed

3 files changed

+136
-92
lines changed

src/alfasim_sdk/alfasim_sdk_api/common.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,8 @@ struct VariableScope
107107
It holds the possible returning error code when trying to open ALFAsim-SDK API.
108108
*/
109109
enum sdk_load_error_code {
110+
SDK_FAILED_TO_LOAD_FUNCTION=-4, /*!< Some function from SDK dll could not be loaded.*/
111+
SDK_FAILED_TO_LOAD_DLL=-3, /*!< SDK dll could not be loaded.*/
110112
SDK_DLL_PATH_TOO_LONG=-2, /*!< Path to SDK dll too long (Windows limitation).*/
111113
SDK_ALREADY_OPEN_ERROR=-1, /*!< SDK dll already Opened.*/
112114
SDK_OK=0 /*!< Everything was fine.*/

src/alfasim_sdk/alfasim_sdk_api/detail/bootstrap_linux.h

Lines changed: 70 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -44,56 +44,80 @@ inline int alfasim_sdk_open(ALFAsimSDK_API* api)
4444
// Load shared object
4545
char *full_filepath = NULL;
4646
asprintf(&full_filepath, "%s%s", alfasim_executable_dir, SO_FILENAME);
47+
48+
// https://www.man7.org/linux/man-pages/man3/dlopen.3.html
49+
// > If dlopen() fails for any reason, it returns NULL.
4750
api->handle = dlopen(full_filepath, RTLD_LAZY);
4851
free(full_filepath);
52+
if (api->handle == NULL) {
53+
return SDK_FAILED_TO_LOAD_DLL;
54+
}
55+
56+
// https://man7.org/linux/man-pages/man3/dlsym.3.html
57+
// > In unusual cases (see NOTES) the value of the symbol could actually be NULL. Therefore,
58+
// > a NULL return from dlsym() need not indicate an error. The correct way to distinguish an
59+
// > error from a symbol whose value is NULL is to call dlerror(3) to clear any old error
60+
// > conditions, then call dlsym(), and then call dlerror(3) again, saving its return value
61+
// > into a variable, and check whether this saved value is not NULL.
62+
#define LOAD_SDK_PROC_MAP_TYPE(func_name, func_type) {\
63+
dlerror();\
64+
api->func_name = (func_type)dlsym(api->handle, #func_name);\
65+
char *last_error = dlerror();\
66+
if (last_error != NULL) {\
67+
dlclose(api->handle);\
68+
api->handle = nullptr;\
69+
return SDK_FAILED_TO_LOAD_FUNCTION;\
70+
}\
71+
}
72+
#define LOAD_SDK_PROC(func_name) LOAD_SDK_PROC_MAP_TYPE(func_name, func_name ## _func)
4973

5074
// Register alfasim API
51-
api->set_plugin_data = (set_plugin_data_func)dlsym(api->handle, "set_plugin_data");
52-
api->get_plugin_data = (get_plugin_data_func)dlsym(api->handle, "get_plugin_data");
53-
api->get_number_of_threads = (get_number_of_threads_func)dlsym(api->handle, "get_number_of_threads");
54-
api->get_thread_id = (get_thread_id_func)dlsym(api->handle, "get_thread_id");
55-
api->get_plugin_input_data_boolean = (get_plugin_input_data_boolean_func)dlsym(api->handle, "get_plugin_input_data_boolean");
56-
api->get_plugin_input_data_enum = (get_plugin_input_data_enum_func)dlsym(api->handle, "get_plugin_input_data_enum");
57-
api->get_plugin_input_data_quantity = (get_plugin_input_data_quantity_func)dlsym(api->handle, "get_plugin_input_data_quantity");
58-
api->get_plugin_input_data_string = (get_plugin_input_data_string_func)dlsym(api->handle, "get_plugin_input_data_string");
59-
api->get_plugin_input_data_string_size = (get_plugin_input_data_string_size_func)dlsym(api->handle, "get_plugin_input_data_string_size");
60-
api->get_plugin_input_data_file_content = (get_plugin_input_data_file_content_func)dlsym(api->handle, "get_plugin_input_data_file_content");
61-
api->get_plugin_input_data_file_content_size = (get_plugin_input_data_file_content_size_func)dlsym(api->handle, "get_plugin_input_data_file_content_size");
62-
api->get_plugin_input_data_reference = (get_plugin_input_data_reference_func)dlsym(api->handle, "get_plugin_input_data_reference");
63-
api->get_plugin_variable = (get_plugin_variable_func)dlsym(api->handle, "get_plugin_variable");
64-
api->get_field_id = (get_field_id_func)dlsym(api->handle, "get_field_id");
65-
api->get_phase_id = (get_phase_id_func)dlsym(api->handle, "get_phase_id");
66-
api->get_layer_id = (get_layer_id_func)dlsym(api->handle, "get_layer_id");
67-
api->get_number_of_fields = (get_number_of_fields_func)dlsym(api->handle, "get_number_of_fields");
68-
api->get_number_of_phases = (get_number_of_phases_func)dlsym(api->handle, "get_number_of_phases");
69-
api->get_number_of_layers = (get_number_of_layers_func)dlsym(api->handle, "get_number_of_layers");
70-
api->get_number_of_phase_pairs = (get_number_of_phase_pairs_func)dlsym(api->handle, "get_number_of_phase_pairs");
71-
api->get_primary_field_id_of_phase = (get_field_id_func)dlsym(api->handle, "get_primary_field_id_of_phase");
72-
api->get_phase_id_of_fields = (get_phase_id_of_fields_func)dlsym(api->handle, "get_phase_id_of_fields");
73-
api->get_field_ids_in_layer = (get_field_ids_in_layer_func)dlsym(api->handle, "get_field_ids_in_layer");
74-
api->get_phase_pair_id = (get_phase_pair_id_func)dlsym(api->handle, "get_phase_pair_id");
75-
api->get_state_variable_array = (get_state_variable_array_func)dlsym(api->handle, "get_state_variable_array");
76-
api->get_simulation_array = (get_simulation_array_func)dlsym(api->handle, "get_simulation_array");
77-
api->get_simulation_tracer_array = (get_simulation_tracer_array_func)dlsym(api->handle, "get_simulation_tracer_array");
78-
api->get_simulation_quantity = (get_simulation_quantity_func)dlsym(api->handle, "get_simulation_quantity");
79-
api->get_wall_interfaces_temperature = (get_wall_interfaces_temperature_func)dlsym(api->handle, "get_wall_interfaces_temperature");
80-
api->get_flow_pattern = (get_flow_pattern_func)dlsym(api->handle, "get_flow_pattern");
81-
api->get_liqliq_flow_pattern = (get_flow_pattern_func)dlsym(api->handle, "get_liqliq_flow_pattern");
82-
api->get_deposition_thickness = (get_deposition_thickness_func)dlsym(api->handle, "get_deposition_thickness");
83-
api->get_plugin_input_data_table_quantity = (get_plugin_input_data_table_quantity_func)dlsym(api->handle, "get_plugin_input_data_table_quantity");
84-
api->get_tracer_id = (get_tracer_id_func)dlsym(api->handle, "get_tracer_id");
85-
api->get_tracer_name_size = (get_tracer_name_size_func)dlsym(api->handle, "get_tracer_name_size");
86-
api->get_tracer_name = (get_tracer_name_func)dlsym(api->handle, "get_tracer_name");
87-
api->get_tracer_ref_by_name = (get_tracer_ref_by_name_func)dlsym(api->handle, "get_tracer_ref_by_name");
88-
api->get_tracer_partition_coefficient = (get_tracer_partition_coefficient_func)dlsym(api->handle, "get_tracer_partition_coefficient");
89-
api->get_plugin_input_data_multiplereference_selected_size = (get_plugin_input_data_multiplereference_selected_size_func)dlsym(api->handle, "get_plugin_input_data_multiplereference_selected_size");
90-
api->get_ucm_friction_factor_input_variable = (get_input_variable_func)dlsym(api->handle, "get_ucm_friction_factor_input_variable");
91-
api->get_ucm_fluid_geometrical_properties = (get_ucm_fluid_geometrical_properties_func)dlsym(api->handle, "get_ucm_fluid_geometrical_properties");
92-
api->get_liq_liq_flow_pattern_input_variable = (get_input_variable_func)dlsym(api->handle, "get_liq_liq_flow_pattern_input_variable");
93-
api->get_liquid_effective_viscosity_input_variable = (get_input_variable_func)dlsym(api->handle, "get_liquid_effective_viscosity_input_variable");
94-
api->get_gas_liq_surface_tension_input_variable = (get_input_variable_func)dlsym(api->handle, "get_gas_liq_surface_tension_input_variable");
95-
api->get_liq_liq_shear_force_per_volume_input_variable = (get_input_variable_func)dlsym(api->handle, "get_liq_liq_shear_force_per_volume_input_variable");
96-
api->get_relative_emulsion_viscosity = (get_relative_emulsion_viscosity_func)dlsym(api->handle, "get_relative_emulsion_viscosity");
75+
LOAD_SDK_PROC(set_plugin_data)
76+
LOAD_SDK_PROC(get_plugin_data)
77+
LOAD_SDK_PROC(get_number_of_threads)
78+
LOAD_SDK_PROC(get_thread_id)
79+
LOAD_SDK_PROC(get_plugin_input_data_boolean)
80+
LOAD_SDK_PROC(get_plugin_input_data_enum)
81+
LOAD_SDK_PROC(get_plugin_input_data_quantity)
82+
LOAD_SDK_PROC(get_plugin_input_data_string)
83+
LOAD_SDK_PROC(get_plugin_input_data_string_size)
84+
LOAD_SDK_PROC(get_plugin_input_data_file_content)
85+
LOAD_SDK_PROC(get_plugin_input_data_file_content_size)
86+
LOAD_SDK_PROC(get_plugin_input_data_reference)
87+
LOAD_SDK_PROC(get_plugin_variable)
88+
LOAD_SDK_PROC(get_field_id)
89+
LOAD_SDK_PROC(get_phase_id)
90+
LOAD_SDK_PROC(get_layer_id)
91+
LOAD_SDK_PROC(get_number_of_fields)
92+
LOAD_SDK_PROC(get_number_of_phases)
93+
LOAD_SDK_PROC(get_number_of_layers)
94+
LOAD_SDK_PROC(get_number_of_phase_pairs)
95+
LOAD_SDK_PROC_MAP_TYPE(get_primary_field_id_of_phase, get_field_id_func)
96+
LOAD_SDK_PROC(get_phase_id_of_fields)
97+
LOAD_SDK_PROC(get_field_ids_in_layer)
98+
LOAD_SDK_PROC(get_phase_pair_id)
99+
LOAD_SDK_PROC(get_state_variable_array)
100+
LOAD_SDK_PROC(get_simulation_array)
101+
LOAD_SDK_PROC(get_simulation_tracer_array)
102+
LOAD_SDK_PROC(get_simulation_quantity)
103+
LOAD_SDK_PROC(get_wall_interfaces_temperature)
104+
LOAD_SDK_PROC(get_flow_pattern)
105+
LOAD_SDK_PROC_MAP_TYPE(get_liqliq_flow_pattern, get_flow_pattern_func)
106+
LOAD_SDK_PROC(get_deposition_thickness)
107+
LOAD_SDK_PROC(get_plugin_input_data_table_quantity)
108+
LOAD_SDK_PROC(get_tracer_id)
109+
LOAD_SDK_PROC(get_tracer_name_size)
110+
LOAD_SDK_PROC(get_tracer_name)
111+
LOAD_SDK_PROC(get_tracer_ref_by_name)
112+
LOAD_SDK_PROC(get_tracer_partition_coefficient)
113+
LOAD_SDK_PROC(get_plugin_input_data_multiplereference_selected_size)
114+
LOAD_SDK_PROC_MAP_TYPE(get_ucm_friction_factor_input_variable, get_input_variable_func)
115+
LOAD_SDK_PROC(get_ucm_fluid_geometrical_properties)
116+
LOAD_SDK_PROC_MAP_TYPE(get_liq_liq_flow_pattern_input_variable, get_input_variable_func)
117+
LOAD_SDK_PROC_MAP_TYPE(get_liquid_effective_viscosity_input_variable, get_input_variable_func)
118+
LOAD_SDK_PROC_MAP_TYPE(get_gas_liq_surface_tension_input_variable, get_input_variable_func)
119+
LOAD_SDK_PROC_MAP_TYPE(get_liq_liq_shear_force_per_volume_input_variable, get_input_variable_func)
120+
LOAD_SDK_PROC(get_relative_emulsion_viscosity)
97121

98122
return SDK_OK;
99123
}

src/alfasim_sdk/alfasim_sdk_api/detail/bootstrap_win.h

Lines changed: 64 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -68,56 +68,74 @@ inline int alfasim_sdk_open(ALFAsimSDK_API* api)
6868
full_filepath[0] = '\0';
6969
StringCchCatW(full_filepath, MAX_PATH_SIZE, alfasim_executable_dir);
7070
StringCchCatW(full_filepath, MAX_PATH_SIZE, DLL_FILENAME);
71+
72+
// https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryw
73+
// > If the function fails, the return value is NULL.
7174
api->handle = LoadLibraryW(full_filepath);
7275
free(executable_dir_from_env);
76+
if (api->handle == NULL) {
77+
return SDK_FAILED_TO_LOAD_DLL;
78+
}
79+
80+
// https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getprocaddress
81+
// > If the function fails, the return value is NULL.
82+
#define LOAD_SDK_PROC_MAP_TYPE(func_name, func_type) {\
83+
api->func_name = (func_type)GetProcAddress(api->handle, #func_name);\
84+
if (api->func_name == NULL) {\
85+
FreeLibrary(api->handle);\
86+
api->handle = nullptr;\
87+
return SDK_FAILED_TO_LOAD_FUNCTION;\
88+
}\
89+
}
90+
#define LOAD_SDK_PROC(func_name) LOAD_SDK_PROC_MAP_TYPE(func_name, func_name ## _func)
7391

7492
// Register alfasim API
75-
api->set_plugin_data = (set_plugin_data_func)GetProcAddress(api->handle, "set_plugin_data");
76-
api->get_plugin_data = (get_plugin_data_func)GetProcAddress(api->handle, "get_plugin_data");
77-
api->get_number_of_threads = (get_number_of_threads_func)GetProcAddress(api->handle, "get_number_of_threads");
78-
api->get_thread_id = (get_thread_id_func)GetProcAddress(api->handle, "get_thread_id");
79-
api->get_plugin_input_data_boolean = (get_plugin_input_data_boolean_func)GetProcAddress(api->handle, "get_plugin_input_data_boolean");
80-
api->get_plugin_input_data_enum = (get_plugin_input_data_enum_func)GetProcAddress(api->handle, "get_plugin_input_data_enum");
81-
api->get_plugin_input_data_quantity = (get_plugin_input_data_quantity_func)GetProcAddress(api->handle, "get_plugin_input_data_quantity");
82-
api->get_plugin_input_data_string = (get_plugin_input_data_string_func)GetProcAddress(api->handle, "get_plugin_input_data_string");
83-
api->get_plugin_input_data_string_size = (get_plugin_input_data_string_size_func)GetProcAddress(api->handle, "get_plugin_input_data_string_size");
84-
api->get_plugin_input_data_file_content = (get_plugin_input_data_file_content_func)GetProcAddress(api->handle, "get_plugin_input_data_file_content");
85-
api->get_plugin_input_data_file_content_size = (get_plugin_input_data_file_content_size_func)GetProcAddress(api->handle, "get_plugin_input_data_file_content_size");
86-
api->get_plugin_input_data_reference = (get_plugin_input_data_reference_func)GetProcAddress(api->handle, "get_plugin_input_data_reference");
87-
api->get_plugin_variable = (get_plugin_variable_func)GetProcAddress(api->handle, "get_plugin_variable");
88-
api->get_field_id = (get_field_id_func)GetProcAddress(api->handle, "get_field_id");
89-
api->get_phase_id = (get_phase_id_func)GetProcAddress(api->handle, "get_phase_id");
90-
api->get_layer_id = (get_layer_id_func)GetProcAddress(api->handle, "get_layer_id");
91-
api->get_number_of_fields = (get_number_of_fields_func)GetProcAddress(api->handle, "get_number_of_fields");
92-
api->get_number_of_phases = (get_number_of_phases_func)GetProcAddress(api->handle, "get_number_of_phases");
93-
api->get_number_of_layers = (get_number_of_layers_func)GetProcAddress(api->handle, "get_number_of_layers");
94-
api->get_number_of_phase_pairs = (get_number_of_phase_pairs_func)GetProcAddress(api->handle, "get_number_of_phase_pairs");
95-
api->get_primary_field_id_of_phase = (get_primary_field_id_of_phase_func)GetProcAddress(api->handle, "get_primary_field_id_of_phase");
96-
api->get_phase_id_of_fields = (get_phase_id_of_fields_func)GetProcAddress(api->handle, "get_phase_id_of_fields");
97-
api->get_field_ids_in_layer = (get_field_ids_in_layer_func)GetProcAddress(api->handle, "get_field_ids_in_layer");
98-
api->get_phase_pair_id = (get_phase_pair_id_func)GetProcAddress(api->handle, "get_phase_pair_id");
99-
api->get_state_variable_array = (get_state_variable_array_func)GetProcAddress(api->handle, "get_state_variable_array");
100-
api->get_simulation_array = (get_simulation_array_func)GetProcAddress(api->handle, "get_simulation_array");
101-
api->get_simulation_tracer_array = (get_simulation_tracer_array_func)GetProcAddress(api->handle, "get_simulation_tracer_array");
102-
api->get_simulation_quantity = (get_simulation_quantity_func)GetProcAddress(api->handle, "get_simulation_quantity");
103-
api->get_wall_interfaces_temperature = (get_wall_interfaces_temperature_func)GetProcAddress(api->handle, "get_wall_interfaces_temperature");
104-
api->get_flow_pattern = (get_flow_pattern_func)GetProcAddress(api->handle, "get_flow_pattern");
105-
api->get_liqliq_flow_pattern = (get_flow_pattern_func)GetProcAddress(api->handle, "get_liqliq_flow_pattern");
106-
api->get_deposition_thickness = (get_deposition_thickness_func)GetProcAddress(api->handle, "get_deposition_thickness");
107-
api->get_plugin_input_data_table_quantity = (get_plugin_input_data_table_quantity_func)GetProcAddress(api->handle, "get_plugin_input_data_table_quantity");
108-
api->get_tracer_id = (get_tracer_id_func)GetProcAddress(api->handle, "get_tracer_id");
109-
api->get_tracer_name_size = (get_tracer_name_size_func)GetProcAddress(api->handle, "get_tracer_name_size");
110-
api->get_tracer_name = (get_tracer_name_func)GetProcAddress(api->handle, "get_tracer_name");
111-
api->get_tracer_ref_by_name = (get_tracer_ref_by_name_func)GetProcAddress(api->handle, "get_tracer_ref_by_name");
112-
api->get_tracer_partition_coefficient = (get_tracer_partition_coefficient_func)GetProcAddress(api->handle, "get_tracer_partition_coefficient");
113-
api->get_plugin_input_data_multiplereference_selected_size = (get_plugin_input_data_multiplereference_selected_size_func)GetProcAddress(api->handle, "get_plugin_input_data_multiplereference_selected_size");
114-
api->get_ucm_friction_factor_input_variable = (get_input_variable_func)GetProcAddress(api->handle, "get_ucm_friction_factor_input_variable");
115-
api->get_ucm_fluid_geometrical_properties = (get_ucm_fluid_geometrical_properties_func)GetProcAddress(api->handle, "get_ucm_fluid_geometrical_properties");
116-
api->get_liq_liq_flow_pattern_input_variable = (get_input_variable_func)GetProcAddress(api->handle, "get_liq_liq_flow_pattern_input_variable");
117-
api->get_liquid_effective_viscosity_input_variable = (get_input_variable_func)GetProcAddress(api->handle, "get_liquid_effective_viscosity_input_variable");
118-
api->get_gas_liq_surface_tension_input_variable = (get_input_variable_func)GetProcAddress(api->handle, "get_gas_liq_surface_tension_input_variable");
119-
api->get_liq_liq_shear_force_per_volume_input_variable = (get_input_variable_func)GetProcAddress(api->handle, "get_liq_liq_shear_force_per_volume_input_variable");
120-
api->get_relative_emulsion_viscosity = (get_relative_emulsion_viscosity_func)GetProcAddress(api->handle, "get_relative_emulsion_viscosity");
93+
LOAD_SDK_PROC(set_plugin_data)
94+
LOAD_SDK_PROC(get_plugin_data)
95+
LOAD_SDK_PROC(get_number_of_threads)
96+
LOAD_SDK_PROC(get_thread_id)
97+
LOAD_SDK_PROC(get_plugin_input_data_boolean)
98+
LOAD_SDK_PROC(get_plugin_input_data_enum)
99+
LOAD_SDK_PROC(get_plugin_input_data_quantity)
100+
LOAD_SDK_PROC(get_plugin_input_data_string)
101+
LOAD_SDK_PROC(get_plugin_input_data_string_size)
102+
LOAD_SDK_PROC(get_plugin_input_data_file_content)
103+
LOAD_SDK_PROC(get_plugin_input_data_file_content_size)
104+
LOAD_SDK_PROC(get_plugin_input_data_reference)
105+
LOAD_SDK_PROC(get_plugin_variable)
106+
LOAD_SDK_PROC(get_field_id)
107+
LOAD_SDK_PROC(get_phase_id)
108+
LOAD_SDK_PROC(get_layer_id)
109+
LOAD_SDK_PROC(get_number_of_fields)
110+
LOAD_SDK_PROC(get_number_of_phases)
111+
LOAD_SDK_PROC(get_number_of_layers)
112+
LOAD_SDK_PROC(get_number_of_phase_pairs)
113+
LOAD_SDK_PROC(get_primary_field_id_of_phase)
114+
LOAD_SDK_PROC(get_phase_id_of_fields)
115+
LOAD_SDK_PROC(get_field_ids_in_layer)
116+
LOAD_SDK_PROC(get_phase_pair_id)
117+
LOAD_SDK_PROC(get_state_variable_array)
118+
LOAD_SDK_PROC(get_simulation_array)
119+
LOAD_SDK_PROC(get_simulation_tracer_array)
120+
LOAD_SDK_PROC(get_simulation_quantity)
121+
LOAD_SDK_PROC(get_wall_interfaces_temperature)
122+
LOAD_SDK_PROC(get_flow_pattern)
123+
LOAD_SDK_PROC_MAP_TYPE(get_liqliq_flow_pattern, get_flow_pattern_func)
124+
LOAD_SDK_PROC(get_deposition_thickness)
125+
LOAD_SDK_PROC(get_plugin_input_data_table_quantity)
126+
LOAD_SDK_PROC(get_tracer_id)
127+
LOAD_SDK_PROC(get_tracer_name_size)
128+
LOAD_SDK_PROC(get_tracer_name)
129+
LOAD_SDK_PROC(get_tracer_ref_by_name)
130+
LOAD_SDK_PROC(get_tracer_partition_coefficient)
131+
LOAD_SDK_PROC(get_plugin_input_data_multiplereference_selected_size)
132+
LOAD_SDK_PROC_MAP_TYPE(get_ucm_friction_factor_input_variable, get_input_variable_func)
133+
LOAD_SDK_PROC(get_ucm_fluid_geometrical_properties)
134+
LOAD_SDK_PROC_MAP_TYPE(get_liq_liq_flow_pattern_input_variable, get_input_variable_func)
135+
LOAD_SDK_PROC_MAP_TYPE(get_liquid_effective_viscosity_input_variable, get_input_variable_func)
136+
LOAD_SDK_PROC_MAP_TYPE(get_gas_liq_surface_tension_input_variable, get_input_variable_func)
137+
LOAD_SDK_PROC_MAP_TYPE(get_liq_liq_shear_force_per_volume_input_variable, get_input_variable_func)
138+
LOAD_SDK_PROC(get_relative_emulsion_viscosity)
121139

122140
return SDK_OK;
123141
}

0 commit comments

Comments
 (0)