mirror of
				https://github.com/bytecodealliance/wasm-micro-runtime.git
				synced 2025-10-31 13:17:31 +00:00 
			
		
		
		
	Fix potential recursive lock in pthread_create_wrapper (#2980)
Potential recursive lock occurs in:
```
pthread_create_wrapper   (acquire exec_env->wait_lock)
  => wasm_cluster_create_thread
    => allocate_aux_stack
      => wasm_runtime_module_malloc_internal
        => wasm_call_function
          => wasm_exec_env_set_thread_info (acquire exec_env->wait_lock again)
```
Allocate aux stack before calling wasm_cluster_create_thread to resolve it.
Reported in https://github.com/bytecodealliance/wasm-micro-runtime/pull/2977.
			
			
This commit is contained in:
		
							parent
							
								
									4a1ad9a160
								
							
						
					
					
						commit
						c39214e8a5
					
				|  | @ -558,6 +558,7 @@ pthread_create_wrapper(wasm_exec_env_t exec_env, | |||
|     ThreadRoutineArgs *routine_args = NULL; | ||||
|     uint32 thread_handle; | ||||
|     uint32 stack_size = 8192; | ||||
|     uint32 aux_stack_start = 0, aux_stack_size; | ||||
|     int32 ret = -1; | ||||
| 
 | ||||
|     bh_assert(module); | ||||
|  | @ -609,10 +610,22 @@ pthread_create_wrapper(wasm_exec_env_t exec_env, | |||
|     routine_args->info_node = info_node; | ||||
|     routine_args->module_inst = new_module_inst; | ||||
| 
 | ||||
|     /* Allocate aux stack previously since exec_env->wait_lock is acquired
 | ||||
|        below, and if the stack is allocated in wasm_cluster_create_thread, | ||||
|        runtime may call the exported malloc function to allocate the stack, | ||||
|        which acquires exec_env->wait again in wasm_exec_env_set_thread_info, | ||||
|        and recursive lock (or hang) occurs */ | ||||
|     if (!wasm_cluster_allocate_aux_stack(exec_env, &aux_stack_start, | ||||
|                                          &aux_stack_size)) { | ||||
|         LOG_ERROR("thread manager error: " | ||||
|                   "failed to allocate aux stack space for new thread"); | ||||
|         goto fail; | ||||
|     } | ||||
| 
 | ||||
|     os_mutex_lock(&exec_env->wait_lock); | ||||
|     ret = | ||||
|         wasm_cluster_create_thread(exec_env, new_module_inst, true, | ||||
|                                    pthread_start_routine, (void *)routine_args); | ||||
|     ret = wasm_cluster_create_thread( | ||||
|         exec_env, new_module_inst, true, aux_stack_start, aux_stack_size, | ||||
|         pthread_start_routine, (void *)routine_args); | ||||
|     if (ret != 0) { | ||||
|         os_mutex_unlock(&exec_env->wait_lock); | ||||
|         goto fail; | ||||
|  | @ -636,6 +649,8 @@ fail: | |||
|         wasm_runtime_free(info_node); | ||||
|     if (routine_args) | ||||
|         wasm_runtime_free(routine_args); | ||||
|     if (aux_stack_start) | ||||
|         wasm_cluster_free_aux_stack(exec_env, aux_stack_start); | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -119,7 +119,7 @@ thread_spawn_wrapper(wasm_exec_env_t exec_env, uint32 start_arg) | |||
|     thread_start_arg->arg = start_arg; | ||||
|     thread_start_arg->start_func = start_func; | ||||
| 
 | ||||
|     ret = wasm_cluster_create_thread(exec_env, new_module_inst, false, | ||||
|     ret = wasm_cluster_create_thread(exec_env, new_module_inst, false, 0, 0, | ||||
|                                      thread_start, thread_start_arg); | ||||
|     if (ret != 0) { | ||||
|         LOG_ERROR("Failed to spawn a new thread"); | ||||
|  |  | |||
|  | @ -208,6 +208,33 @@ free_aux_stack(WASMExecEnv *exec_env, uint32 start) | |||
| #endif | ||||
| } | ||||
| 
 | ||||
| bool | ||||
| wasm_cluster_allocate_aux_stack(WASMExecEnv *exec_env, uint32 *p_start, | ||||
|                                 uint32 *p_size) | ||||
| { | ||||
|     WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env); | ||||
|     bool ret; | ||||
| 
 | ||||
|     os_mutex_lock(&cluster->lock); | ||||
|     ret = allocate_aux_stack(exec_env, p_start, p_size); | ||||
|     os_mutex_unlock(&cluster->lock); | ||||
| 
 | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| bool | ||||
| wasm_cluster_free_aux_stack(WASMExecEnv *exec_env, uint32 start) | ||||
| { | ||||
|     WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env); | ||||
|     bool ret; | ||||
| 
 | ||||
|     os_mutex_lock(&cluster->lock); | ||||
|     ret = free_aux_stack(exec_env, start); | ||||
|     os_mutex_unlock(&cluster->lock); | ||||
| 
 | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| WASMCluster * | ||||
| wasm_cluster_create(WASMExecEnv *exec_env) | ||||
| { | ||||
|  | @ -654,12 +681,13 @@ thread_manager_start_routine(void *arg) | |||
| 
 | ||||
| int32 | ||||
| wasm_cluster_create_thread(WASMExecEnv *exec_env, | ||||
|                            wasm_module_inst_t module_inst, bool alloc_aux_stack, | ||||
|                            wasm_module_inst_t module_inst, | ||||
|                            bool is_aux_stack_allocated, uint32 aux_stack_start, | ||||
|                            uint32 aux_stack_size, | ||||
|                            void *(*thread_routine)(void *), void *arg) | ||||
| { | ||||
|     WASMCluster *cluster; | ||||
|     WASMExecEnv *new_exec_env; | ||||
|     uint32 aux_stack_start = 0, aux_stack_size; | ||||
|     korp_tid tid; | ||||
| 
 | ||||
|     cluster = wasm_exec_env_get_cluster(exec_env); | ||||
|  | @ -676,17 +704,11 @@ wasm_cluster_create_thread(WASMExecEnv *exec_env, | |||
|     if (!new_exec_env) | ||||
|         goto fail1; | ||||
| 
 | ||||
|     if (alloc_aux_stack) { | ||||
|         if (!allocate_aux_stack(exec_env, &aux_stack_start, &aux_stack_size)) { | ||||
|             LOG_ERROR("thread manager error: " | ||||
|                       "failed to allocate aux stack space for new thread"); | ||||
|             goto fail2; | ||||
|         } | ||||
| 
 | ||||
|     if (is_aux_stack_allocated) { | ||||
|         /* Set aux stack for current thread */ | ||||
|         if (!wasm_exec_env_set_aux_stack(new_exec_env, aux_stack_start, | ||||
|                                          aux_stack_size)) { | ||||
|             goto fail3; | ||||
|             goto fail2; | ||||
|         } | ||||
|     } | ||||
|     else { | ||||
|  | @ -699,7 +721,7 @@ wasm_cluster_create_thread(WASMExecEnv *exec_env, | |||
|     new_exec_env->suspend_flags.flags = exec_env->suspend_flags.flags; | ||||
| 
 | ||||
|     if (!wasm_cluster_add_exec_env(cluster, new_exec_env)) | ||||
|         goto fail3; | ||||
|         goto fail2; | ||||
| 
 | ||||
|     new_exec_env->thread_start_routine = thread_routine; | ||||
|     new_exec_env->thread_arg = arg; | ||||
|  | @ -711,7 +733,7 @@ wasm_cluster_create_thread(WASMExecEnv *exec_env, | |||
|                             (void *)new_exec_env, | ||||
|                             APP_THREAD_STACK_SIZE_DEFAULT)) { | ||||
|         os_mutex_unlock(&new_exec_env->wait_lock); | ||||
|         goto fail4; | ||||
|         goto fail3; | ||||
|     } | ||||
| 
 | ||||
|     /* Wait until the new_exec_env->handle is set to avoid it is
 | ||||
|  | @ -723,12 +745,8 @@ wasm_cluster_create_thread(WASMExecEnv *exec_env, | |||
| 
 | ||||
|     return 0; | ||||
| 
 | ||||
| fail4: | ||||
|     wasm_cluster_del_exec_env_internal(cluster, new_exec_env, false); | ||||
| fail3: | ||||
|     /* free the allocated aux stack space */ | ||||
|     if (alloc_aux_stack) | ||||
|         free_aux_stack(exec_env, aux_stack_start); | ||||
|     wasm_cluster_del_exec_env_internal(cluster, new_exec_env, false); | ||||
| fail2: | ||||
|     wasm_exec_env_destroy_internal(new_exec_env); | ||||
| fail1: | ||||
|  |  | |||
|  | @ -81,7 +81,9 @@ wasm_cluster_dup_c_api_imports(WASMModuleInstanceCommon *module_inst_dst, | |||
| 
 | ||||
| int32 | ||||
| wasm_cluster_create_thread(WASMExecEnv *exec_env, | ||||
|                            wasm_module_inst_t module_inst, bool alloc_aux_stack, | ||||
|                            wasm_module_inst_t module_inst, | ||||
|                            bool is_aux_stack_allocated, uint32 aux_stack_start, | ||||
|                            uint32 aux_stack_size, | ||||
|                            void *(*thread_routine)(void *), void *arg); | ||||
| 
 | ||||
| int32 | ||||
|  | @ -221,6 +223,13 @@ wasm_cluster_traverse_lock(WASMExecEnv *exec_env); | |||
| void | ||||
| wasm_cluster_traverse_unlock(WASMExecEnv *exec_env); | ||||
| 
 | ||||
| bool | ||||
| wasm_cluster_allocate_aux_stack(WASMExecEnv *exec_env, uint32 *p_start, | ||||
|                                 uint32 *p_size); | ||||
| 
 | ||||
| bool | ||||
| wasm_cluster_free_aux_stack(WASMExecEnv *exec_env, uint32 start); | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Wenyong Huang
						Wenyong Huang