1. 程式人生 > >golang的一個執行緒排程被停止的問題處理

golang的一個執行緒排程被停止的問題處理

最近發現, golang寫的遊戲伺服器, 在非除錯狀態下, 一切正常, 但是在掛接gdb除錯時, 無法收到網路訊息. 打了很多日誌, 發現, 只要有goroutine的地方, 都沒有切換進入.

回想了下, goroutine的排程規則: 1.4之前, 在碰到syscall時, goroutine會被排程並處理. 1.4後, 只要有函式呼叫時, 均會進行一次排程. 密度比以前增加了, 更加接近真執行緒的處理.

根據這個原理, 問題應該出現在伺服器底層沒有給系統提供排程機會的點上. 我們的伺服器通過一個bool型的chan進行阻塞, 讓伺服器維持阻塞進行訊息處理不退出. 但是最近為了在windows下提供命令列支援, 增加了一些程式碼, 如下

   1:  func WaitForExit() {
   2:   
   3:      if len(peerMap) == 0 {
   4:          log.Println("no peer running, exit!")
   5:          return
   6:      }
   7:   
   8:      // 命令列功能只在windows下啟用
   9:      if runtime.GOOS == "windows" {
  10:          reader := bufio.NewReader(os.Stdin)
  11:   
  12:          var running bool
= true
  13:   
  14:          go func() {
  15:              select {
  16:              case <-exitChan:
  17:                  running = false
  18:              }
  19:          }()
  20:   
  21:          for running {
  22:              data, _, _ := reader.ReadLine()
  23:              command := string
(data)
  24:   
  25:              dispatchConsoleCommand(command)
  26:          }
  27:      } else {
  28:          // Linux環境
  29:          <-exitChan
  30:      }
  31:   
  32:  }

我暫時遮蔽了新加的這套功能, 維持<-exitChan, 問題馬上解決

結合前面的猜測, 我估計在reader.ReadLine()函式內, 沒有給底層提供排程的機會, 導致其他goroutine無法執行, 造成伺服器卡死

技術討論群:  309800774 歡迎golang愛好者加入, 純技術研討