Better task state error and fix cancel error issue in the example (#637)

diff --git a/examples/python/mesapy_deadloop_cancel.py b/examples/python/mesapy_deadloop_cancel.py
index 2bd7206..a4b0eaa 100644
--- a/examples/python/mesapy_deadloop_cancel.py
+++ b/examples/python/mesapy_deadloop_cancel.py
@@ -75,22 +75,22 @@
         result = client.get_task(task_id)
         if result["status"] != TaskStatus.Canceled:
             print("[+] Task is not canceled, cancel again")
-            client.cancel_task(task_id)
+            try:
+                client.cancel_task(task_id)
+            except Exception as e:
+                # this happens when the task has already been canceled
+                print(f"[-] cancel task failed, reason: {str(e)}")
 
         try:
             result = client.get_task_result(task_id)
         except Exception as e:
-            print(f"[+] result: {str(e)}")
-            result = str(e)
-
-        return result
+            # this is expected, since the task is cancelled
+            print(f"[-] getting result failed, reason: {str(e)}")
 
 
 def main():
     example = MesaPyEchoExample(USER_ID, USER_PASSWORD)
-    rv = example.deadloop()
-
-    print("[+] function return: ", rv)
+    example.deadloop()
 
 
 if __name__ == '__main__':
diff --git a/services/management/enclave/src/error.rs b/services/management/enclave/src/error.rs
index 0b77153..952fa30 100644
--- a/services/management/enclave/src/error.rs
+++ b/services/management/enclave/src/error.rs
@@ -39,8 +39,14 @@
     InvalidTaskId,
     #[error("invalid task")]
     InvalidTask,
-    #[error("failed to change task state")]
-    TaskStateError,
+    #[error("failed to assign data to task")]
+    TaskAssignDataError,
+    #[error("failed to approve task")]
+    TaskApproveError,
+    #[error("failed to invoke task")]
+    TaskInvokeError,
+    #[error("failed to cancel task, reason: {0}")]
+    TaskCancelError(String),
 }
 
 impl From<ManagementServiceError> for TeaclaveServiceResponseError {
diff --git a/services/management/enclave/src/service.rs b/services/management/enclave/src/service.rs
index c0d2d20..a69124b 100644
--- a/services/management/enclave/src/service.rs
+++ b/services/management/enclave/src/service.rs
@@ -600,7 +600,7 @@
 
         let mut task: Task<Assign> = ts.try_into().map_err(|e| {
             log::warn!("Assign state error: {:?}", e);
-            ManagementServiceError::TaskStateError
+            ManagementServiceError::TaskAssignDataError
         })?;
 
         for (data_name, data_id) in request.inputs.iter() {
@@ -643,7 +643,7 @@
 
         let mut task: Task<Approve> = ts.try_into().map_err(|e| {
             log::warn!("Approve state error: {:?}", e);
-            ManagementServiceError::TaskStateError
+            ManagementServiceError::TaskApproveError
         })?;
 
         task.approve(&user_id)
@@ -685,7 +685,7 @@
 
         let mut task: Task<Stage> = ts.try_into().map_err(|e| {
             log::warn!("Stage state error: {:?}", e);
-            ManagementServiceError::TaskStateError
+            ManagementServiceError::TaskInvokeError
         })?;
 
         log::debug!("InvokeTask: get task: {:?}", task);
@@ -736,7 +736,9 @@
                 // race will not affect correctness/privacy
                 let mut task: Task<Cancel> = ts.try_into().map_err(|e| {
                     log::warn!("Cancel state error: {:?}", e);
-                    ManagementServiceError::TaskStateError
+                    ManagementServiceError::TaskCancelError(
+                        "task has already been canceled".to_string(),
+                    )
                 })?;
 
                 log::debug!("Canceled Task: {:?}", task);
@@ -744,7 +746,9 @@
                 task.update_result(TaskResult::Err(TaskFailure {
                     reason: "Task canceled".to_string(),
                 }))
-                .map_err(|_| ManagementServiceError::TaskStateError)?;
+                .map_err(|_| {
+                    ManagementServiceError::TaskCancelError("cannot update result".to_string())
+                })?;
                 let ts: TaskState = task.into();
                 self.write_to_db(&ts)?;