战魂小筑

讨论群:309800774 知乎关注:http://zhihu.com/people/sunicdavy 开源项目:https://github.com/davyxu

   :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  257 随笔 :: 0 文章 :: 506 评论 :: 0 Trackbacks

最近发现, 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爱好者加入, 纯技术研讨

posted on 2015-01-30 16:25 战魂小筑 阅读(3661) 评论(1)  编辑 收藏 引用 所属分类: 网络 服务器技术

评论

# re: golang的一个线程调度被停止的问题处理 2015-01-30 20:40 战魂小筑
package main

import (
"bufio"
"log"
"os"
)

func main() {

go func() {
log.Println("here")
}()

reader := bufio.NewReader(os.Stdin)

data, _, _ := reader.ReadLine()

log.Println("%s", string(data))

}
用调试器挂接这个例子, 是看不到here的  回复  更多评论
  


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理