diff --git a/pkg/cloudcommon/db/taskman/tasks.go b/pkg/cloudcommon/db/taskman/tasks.go index 95bd7b1efd..02691d567b 100644 --- a/pkg/cloudcommon/db/taskman/tasks.go +++ b/pkg/cloudcommon/db/taskman/tasks.go @@ -21,6 +21,7 @@ import ( "net/http" "reflect" "runtime/debug" + "sort" "strconv" "strings" "time" @@ -275,9 +276,6 @@ func (manager *STaskManager) NewTask( return nil, fmt.Errorf("task %s not found", taskName) } - lockman.LockObject(ctx, obj) - defer lockman.ReleaseObject(ctx, obj) - data := fetchTaskParams(ctx, taskName, taskData, parentTaskId, parentTaskNotifyUrl, pendingUsage) task := &STask{ ObjName: obj.Keyword(), @@ -325,8 +323,6 @@ func (manager *STaskManager) NewParallelTask( } log.Debugf("number of objs: %d", len(objs)) - lockman.LockClass(ctx, objs[0].GetModelManager(), userCred.GetProjectId()) - defer lockman.ReleaseClass(ctx, objs[0].GetModelManager(), userCred.GetProjectId()) data := fetchTaskParams(ctx, taskName, taskData, parentTaskId, parentTaskNotifyUrl, pendingUsage) task := &STask{ @@ -343,15 +339,17 @@ func (manager *STaskManager) NewParallelTask( log.Errorf("Task insert error %s", err) return nil, err } + for _, obj := range objs { to := STaskObject{TaskId: task.Id, ObjId: obj.GetId()} to.SetModelManager(TaskObjectManager, &to) err := TaskObjectManager.TableSpec().Insert(ctx, &to) if err != nil { log.Errorf("Taskobject insert error %s", err) - return nil, err + return nil, errors.Wrap(err, "insert task object") } } + parentTask := task.GetParentTask() if parentTask != nil { st := SSubTask{TaskId: parentTask.Id, Stage: parentTask.Stage, SubtaskId: task.Id} @@ -411,6 +409,12 @@ func (manager *STaskManager) execTask(taskId string, data jsonutils.JSONObject) } } +type sSortedObjects []db.IStandaloneModel + +func (a sSortedObjects) Len() int { return len(a) } +func (a sSortedObjects) Swap(i, j int) { a[i], a[j] = a[j], a[i] } +func (a sSortedObjects) Less(i, j int) bool { return a[i].GetId() < a[j].GetId() } + func execITask(taskValue reflect.Value, task *STask, odata jsonutils.JSONObject, isMulti bool) { ctxData := task.GetRequestContext() ctx := ctxData.GetContext() @@ -514,8 +518,13 @@ func execITask(taskValue reflect.Value, task *STask, odata jsonutils.JSONObject, } task.taskObjects = objs - lockman.LockClass(ctx, objResManager, task.UserCred.GetProjectId()) - defer lockman.ReleaseClass(ctx, objResManager, task.UserCred.GetProjectId()) + // sort objects by ids to avoid deadlock + sort.Sort(sSortedObjects(objs)) + + for i := range objs { + lockman.LockObject(ctx, objs[i]) + defer lockman.ReleaseObject(ctx, objs[i]) + } params[1] = reflect.ValueOf(objs) } else {