# linux2021: foxhoundsk ## 測驗 δ -- 1 實作缺失位於函式 `con_pop` 中: ```cpp node_t *node = queue->first; /* Node to be removed */ node_t *new_header = queue->first->next; /* become the first in the queue */ /* Queue is empty */ if (!new_header) { mtx_unlock(queue->first_mutex); return NULL; } ``` 其中指標 `node` 要提取的節點不應為 `queue->first`,因為第一次執行 pop 操作時,會將 dummy 節點取出。 後者用於保證 queue 的頭尾 (`first` 以及 `last`) 一致性。倘若將其提取出來,queue 會在經歷至少一次的 pop/push 操作並且只剩一個節點時,無法將最後一個節點取出,因為本實做需要 dummy 節點總是存在。 也就是說,發生問題時,即便 queue 中仍然有未處理的節點,應用程式還是會拿到 NULL (表示 queue 中沒有未處理的節點),而不是最後一個節點的內容。 因此,此程式實際運作時,最後一個要提取存放 kill signal 的節點的 pop thread 總是無法完成提取操作,進而無法讓 `thrd_join` 完成等待。 ### 解決方法 可以將 `con_pop` 修改為: ```diff= void *con_pop(con_queue_t *queue) { mtx_lock(queue->first_mutex); -- node_t *node = queue->first; /* Node to be removed */ -- node_t *new_header = queue->first->next; /* become the first in the queue */ ++ node_t *node = queue->first->next; /* Node to be removed */ /* Queue is empty */ -- if (!new_header) { ++ if (!node) { mtx_unlock(queue->first_mutex); return NULL; } /* Queue not empty: retrieve data and rewire */ void *return_value = node->value; /* BBB */ -- queue->first->next = new_header; ++ queue->first->next = node->next; mtx_unlock(queue->first_mutex); /* Free removed node and return */ free(node); return return_value; } ``` 以使得執行 pop 操作時,總是提取從 `first` 算起的第二個節點,也就是應用程式感興趣的最舊的節點 (`queue->first->next`),以解決第一次呼叫 `con_pop` 時,將 dummy 節點移出 queue 的問題。 :::info 答案 BBB (L17) 貌似不是 `node->value` ? ::: ## 測驗 δ -- 2 ## 測驗 ϵ -- 1 ## 測驗 ϵ -- 2 ## 測驗 ζ -- 1 ## 測驗 ζ -- 2