本文整理匯總了Golang中utils.PrintPanicStack函數的典型用法代碼示例。如果您正苦於以下問題:Golang PrintPanicStack函數的具體用法?Golang PrintPanicStack怎麽用?Golang PrintPanicStack使用的例子?那麽, 這裏精選的函數代碼示例或許可以為您提供幫助。
在下文中一共展示了PrintPanicStack函數的15個代碼示例,這些例子默認根據受歡迎程度排序。您可以為喜歡或者感覺有用的代碼點讚,您的評價將有助於係統推薦出更棒的Golang代碼示例。
示例1: agent
// PIPELINE #2: agent
// all the packets from handleClient() will be handled
func agent(sess *Session, in chan []byte, out *Buffer) {
defer wg.Done() // will decrease waitgroup by one, useful for manual server shutdown
defer utils.PrintPanicStack()
// init session
sess.MQ = make(chan pb.Game_Frame, DEFAULT_MQ_SIZE)
sess.ConnectTime = time.Now()
sess.LastPacketTime = time.Now()
// minute timer
min_timer := time.After(time.Minute)
// cleanup work
defer func() {
close(sess.Die)
if sess.Stream != nil {
sess.Stream.CloseSend()
}
}()
// >> the main message loop <<
// handles 4 types of message:
// 1. from client
// 2. from game service
// 3. timer
// 4. server shutdown signal
for {
select {
case msg, ok := <-in: // packet from network
if !ok {
return
}
sess.PacketCount++
sess.PacketTime = time.Now()
if result := proxy_user_request(sess, msg); result != nil {
out.send(sess, result)
}
sess.LastPacketTime = sess.PacketTime
case frame := <-sess.MQ: // packets from game
switch frame.Type {
case pb.Game_Message:
out.send(sess, frame.Message)
case pb.Game_Kick:
sess.Flag |= SESS_KICKED_OUT
}
case <-min_timer: // minutes timer
timer_work(sess, out)
min_timer = time.After(time.Minute)
case <-die: // server is shuting down...
sess.Flag |= SESS_KICKED_OUT
}
// see if the player should be kicked out.
if sess.Flag&SESS_KICKED_OUT != 0 {
return
}
}
}
示例2: agent
// agent of user
func agent(sess *Session, in chan []byte, out *Buffer, sess_die chan bool) {
defer wg.Done()
defer utils.PrintPanicStack()
// init session
sess.MQ = make(chan spp.Game_Frame, DEFAULT_MQ_SIZE)
sess.ConnectTime = time.Now()
sess.LastPacketTime = time.Now()
// minute timer
min_timer := time.After(time.Minute)
// cleanup work
defer func() {
close(sess_die)
if sess.Stream != nil {
sess.Stream.CloseSend()
}
}()
// >> the main message loop <<
for {
select {
case msg, ok := <-in: // packet from network
if !ok {
return
}
sess.PacketCount++
sess.PacketTime = time.Now()
if result := proxy_user_request(sess, msg); result != nil {
out.send(sess, result)
}
sess.LastPacketTime = sess.PacketTime
case frame := <-sess.MQ:
switch frame.Type {
case spp.Game_Message:
out.send(sess, frame.Message)
case spp.Game_Kick:
sess.Flag |= SESS_KICKED_OUT
}
case <-min_timer: // minutes timer
timer_work(sess, out)
min_timer = time.After(time.Minute)
case <-die: // server is shuting down...
sess.Flag |= SESS_KICKED_OUT
}
// see if the player should be kicked out.
if sess.Flag&SESS_KICKED_OUT != 0 {
return
}
}
}
示例3: start
// packet sending goroutine
func (buf *Buffer) start() {
defer utils.PrintPanicStack()
for {
select {
case data := <-buf.pending:
buf.raw_send(data)
case <-buf.ctrl: // receive session end signal
close(buf.pending)
// close the connection
buf.conn.Close()
return
}
}
}
示例4: main
func main() {
// to catch all uncaught panic
defer utils.PrintPanicStack()
// open profiling
go func() {
log.Info(http.ListenAndServe("0.0.0.0:6060", nil))
}()
// set log prefix
log.SetPrefix(SERVICE)
// resolve address & start listening
tcpAddr, err := net.ResolveTCPAddr("tcp4", _port)
checkError(err)
listener, err := net.ListenTCP("tcp", tcpAddr)
checkError(err)
log.Info("listening on:", listener.Addr())
// startup
startup()
LOOP:
// loop accepting
for {
conn, err := listener.AcceptTCP()
if err != nil {
log.Warning("accept failed:", err)
continue
}
go handleClient(conn) // start a goroutine for every incoming connection for reading
// check server close signal
select {
case <-die:
listener.Close()
break LOOP
default:
}
}
// server closed, wait forever
// other options:
// select{} -- may cause deadlock detected error, not tested yet
for {
<-time.After(time.Second)
}
}
示例5: main
func main() {
defer utils.PrintPanicStack()
go func() {
log.Info(http.ListenAndServe("0.0.0.0:6060", nil))
}()
log.SetPrefix(SERVICE)
// resolve
tcpAddr, err := net.ResolveTCPAddr("tcp4", _port)
checkError(err)
listener, err := net.ListenTCP("tcp", tcpAddr)
checkError(err)
log.Info("listening on:", listener.Addr())
// init services
sp.Init()
// startup
startup()
// loop accepting
LOOP:
for {
conn, err := listener.AcceptTCP()
if err != nil {
log.Warning("accept failed:", err)
continue
}
go handleClient(conn)
// check server close signal
select {
case <-die:
listener.Close()
break LOOP
default:
}
}
// server closed, wait forever
for {
<-time.After(time.Second)
}
}
示例6: sig_handler
// handle unix signals
func sig_handler() {
defer utils.PrintPanicStack()
ch := make(chan os.Signal, 1)
signal.Notify(ch, syscall.SIGTERM)
for {
msg := <-ch
switch msg {
case syscall.SIGTERM: // 關閉agent
close(die)
log.Info("sigterm received")
log.Info("waiting for agents close, please wait...")
wg.Wait()
log.Info("agent shutdown.")
os.Exit(0)
}
}
}
示例7: start
// packet sending goroutine
// 數據包發送協程
func (buf *Buffer) start() {
defer utils.PrintPanicStack()
for {
select {
//監聽數據包管道
case data := <-buf.pending:
buf.raw_send(data)
//監聽關閉管道
//?Important
//ctrl 指向的是 sess_die, 在main.go裏麵,已經有select監聽了? 此處會不會造成問題
case <-buf.ctrl: //receive session end signal
//關閉接收管道
close(buf.pending)
//關閉conn連接
buf.conn.Close()
return
}
}
}
示例8: main
//遊戲入口
func main() {
defer utils.PrintPanicStack()
go func() {
log.Info(http.ListenAndServe("0.0.0.0:6060", nil))
}()
log.SetPrefix(SERVICE)
tcpAddr, err := net.ResolveTCPAddr("tcp4", _port)
checkError(err)
listener, err := net.ListenTCP("tcp", tcpAddr)
checkError(err)
log.Info("listening on:", listener.Addr())
// loop accepting
for {
conn, err := listener.AcceptTCP()
if err != nil {
log.Warning("accept failed:", err)
continue
}
go handleClient(conn)
// check server close signal
select {
case <-die:
listener.Close()
goto FINAL
default:
}
}
FINAL:
// server closed, wait forever
// 此處為什麽要等1秒
// 此處等待1秒鍾,隻是為了wg.Wait() 可以執行到,從而阻塞主線程
for {
<-time.After(time.Second)
}
}
示例9: proxy_user_request
// client protocol handle proxy
func proxy_user_request(sess *Session, p []byte) []byte {
start := time.Now()
defer utils.PrintPanicStack()
//解密
if sess.Flag&SESS_ENCRYPT != 0 {
//使用2組密鑰匙, 增加破解難度
sess.Decoder.XORKeyStream(p, p)
}
//封裝成reader
reader := packet.Reader(p)
// 讀客戶端數據包序列號(1,2,3...)
// 可避免重放攻擊-REPLAY-ATTACK
//數據包的前4個字節存放的是客戶端的發包數量
//客戶端每次發包要包含第幾次發包信息
seq_id, err := reader.ReadU32()
if err != nil {
log.Error("read client timestamp failed:", err)
sess.Flag |= SESS_KICKED_OUT
return nil
}
// 數據包個數驗證
if seq_id != sess.PacketCount {
//數據包真實長度是,總長度-4個字節的包個數長度-2個字節的協議號長度
log.Errorf("illegal packet sequeue id:%v should be:%v size:%v", seq_id, sess.PacketCount, len(p)-6)
sess.Flag |= SESS_KICKED_OUT
return nil
}
// 讀協議號
b, err := reader.ReadS16()
if err != nil {
log.Error("read protocol number failed.")
sess.Flag |= SESS_KICKED_OUT
return nil
}
//根據協議號段 做服務劃分
var ret []byte
if b > MAX_PROTO_NUM {
//去除4字節發包個數,將其餘的向前傳遞
if err := forward(sess, p[4:]); err != nil {
log.Errorf("service id:%v execute failed, error:%v", b, err)
sess.Flag |= SESS_KICKED_OUT
return nil
}
} else {
if h := client_handler.Handlers[b]; h != nil {
ret = h(sess, reader)
} else {
log.Errorf("service id:%v not bind", b)
sess.Flag |= SESS_KICKED_OUT
return nil
}
}
// 統計處理時間
elasped := time.Now().Sub(start)
if b != 0 { //排除心跳包日誌
log.Trace("[REQ]", client_handler.RCode[b])
_statter.Timing(1.0, fmt.Sprintf("%v%v", STATSD_PREFIX, client_handler.RCode[b]), elasped)
}
return ret
}
示例10: handleClient
// start a goroutine when a new connection is accepted
func handleClient(conn *net.TCPConn) {
defer utils.PrintPanicStack()
// set per-connection socket buffer
conn.SetReadBuffer(SO_RCVBUF)
// set initial socket buffer
conn.SetWriteBuffer(SO_SNDBUF)
// initial network control struct
header := make([]byte, 2)
in := make(chan []byte)
defer func() {
close(in) // session will close
}()
// create a new session object for the connection
var sess Session
host, port, err := net.SplitHostPort(conn.RemoteAddr().String())
if err != nil {
log.Error("cannot get remote address:", err)
return
}
sess.IP = net.ParseIP(host)
log.Infof("new connection from:%v port:%v", host, port)
// session die signal
sess.Die = make(chan struct{})
// create a write buffer
out := new_buffer(conn, sess.Die)
go out.start()
// start one agent for handling packet
wg.Add(1)
go agent(&sess, in, out)
// network loop
for {
// solve dead link problem
conn.SetReadDeadline(time.Now().Add(TCP_READ_DEADLINE * time.Second))
n, err := io.ReadFull(conn, header)
if err != nil {
log.Warningf("read header failed, ip:%v reason:%v size:%v", sess.IP, err, n)
return
}
size := binary.BigEndian.Uint16(header)
// alloc a byte slice for reading
payload := make([]byte, size)
// read msg
n, err = io.ReadFull(conn, payload)
if err != nil {
log.Warningf("read payload failed, ip:%v reason:%v size:%v", sess.IP, err, n)
return
}
select {
case in <- payload: // payload queued
case <-sess.Die:
log.Warningf("connection closed by logic, flag:%v ip:%v", sess.Flag, sess.IP)
return
}
}
}
示例11: proxy_user_request
// client protocol handle proxy
func proxy_user_request(sess *Session, p []byte) []byte {
start := time.Now()
defer utils.PrintPanicStack(sess, p)
// 解密
if sess.Flag&SESS_ENCRYPT != 0 {
sess.Decoder.Codec(p)
}
// 封裝為reader
reader := packet.Reader(p)
// 讀客戶端數據包序列號(1,2,3...)
// 可避免重放攻擊-REPLAY-ATTACK
seq_id, err := reader.ReadU32()
if err != nil {
log.Error("read client timestamp failed:", err)
sess.Flag |= SESS_KICKED_OUT
return nil
}
// 讀協議號
b, err := reader.ReadS16()
if err != nil {
log.Error("read protocol number failed.")
sess.Flag |= SESS_KICKED_OUT
return nil
}
// 數據包序列號驗證
if seq_id != sess.PacketCount {
log.Errorf("illegal packet sequence id:%v should be:%v proto:%v size:%v", seq_id, sess.PacketCount, b, len(p)-6)
sess.Flag |= SESS_KICKED_OUT
return nil
}
var ret []byte
if b > MAX_PROTO_NUM { // game協議
// 透傳
ret, err = forward(sess, p)
if err != nil {
log.Errorf("service id:%v execute failed", b)
sess.Flag |= SESS_KICKED_OUT
return nil
}
} else { // agent保留協議段 [0, MAX_PROTO_NUM]
// handle有效性檢查
h := client_handler.Handlers[b]
if h == nil {
log.Errorf("service id:%v not bind", b)
sess.Flag |= SESS_KICKED_OUT
return nil
}
// 執行
ret = h(sess, reader)
}
// 統計處理時間
elasped := time.Now().Sub(start)
if b != 0 { // 排除心跳包日誌
log.Trace("[REQ]", b)
_statter.Timing(1.0, fmt.Sprintf("%v%v", STATSD_PREFIX, b), elasped)
}
return ret
}
示例12: handleClient
// start a goroutine when a new connection is accepted
func handleClient(conn *net.TCPConn) {
defer utils.PrintPanicStack()
// set per-connection socket buffer
//設置conn連接接受緩存的大小, 當超過緩存時, 會進入阻塞狀態,等待被讀取
conn.SetReadBuffer(SO_RCVBUF)
// set initial socket buffer
//設置conn連接發送緩存的大小, 當超過緩存時, 會進入阻塞狀態,等待被發送成功
conn.SetWriteBuffer(SO_SNDBUF)
// initial network control struct
// 初始化2個字節數組, 用於存儲header長度, 既後麵要讀取的文件長度
header := make([]byte, 2)
// 輸入流通道, 解析後的數據將放入,等待被處理
in := make(chan []byte)
//設置延遲函數,當玩家斷開連接時, 函數退出之前,關閉輸入流
defer func() {
close(in) // session will close
}()
// create a new session object for the connection
//創建session對象, 用於封裝客戶端和服務器的信息交換
var sess Session
host, port, err := net.SplitHostPort(conn.RemoteAddr().String())
if err != nil {
log.Error("cannot get remote address:", err)
return
}
//存儲用戶ip
sess.IP = net.ParseIP(host)
//打印用戶的ip和端口, 用戶可能會雙開?
log.Infof("new connection from:%v port:%v", host, port)
// session die signal
sess_die := make(chan bool)
//SESSION_DIE 監控有問題.................
// create a write buffer
// 創建寫入buffer對象
out := new_buffer(conn, sess_die)
go out.start()
// start one agent for handling packet
//記錄goroutine個數,讓係統接收到關閉命令後,會阻塞主線程,至少所有agent線程退出,已保證數據落地
wg.Add(1)
go agent(&sess, in, out, sess_die)
//network loop
for {
// solve dead line problem
// 設置讀超時時間, 如果在任意一次執行Read syscall 返回的時候,超過這個時間點, 則算超時
conn.SetReadDeadline(time.Now().Add(TCP_READ_DEADLINE * time.Second))
//先讀取2個字節頭文件長度
n, err := io.ReadFull(conn, header)
if err != nil {
log.Warningf("read header failed, ip:%v reason:%v size:%v", sess.IP, err, n)
return
}
//將2個字節數組轉成int16類型, 不丟失精度
size := binary.BigEndian.Uint16(header)
// alloc a byte slice for reading
// 創建一個指定長度的切片,用於存放具體內容
payload := make([]byte, size)
//read msg
n, err = io.ReadFull(conn, payload)
if err != nil {
log.Warningf("read payload failed, ip:%v reason:%v size:%v", sess.IP, err, n)
return
}
select {
//接收的數據,轉入in通道
case in <- payload: //payload queued
//監聽sess_die 通道
case <-sess_die:
log.Warning("connection closed by logic, flag:%v ip:%v", sess.Flag, sess.IP)
return
}
}
// 好像沒有處理連接超時, 如果玩家連上遊戲後,一直未操作,再次鏈接時,會是新的連接?難道客戶端在許久沒有操作的情況下,先發一次ping, 如果有響應,繼續操作,如果沒響應,則執行重連?
// 如果玩家已經退出了遊戲,但是通過非正常途徑退出的,這時,服務器還保留著該session, 當玩家再次登陸時, 原先的連接何時刪除
}
示例13: proxy_user_request
// client protocol handle proxy
func proxy_user_request(sess *Session, p []byte) []byte {
start := time.Now()
defer utils.PrintPanicStack(sess, p)
// 解密
if sess.Flag&SESS_ENCRYPT != 0 {
sess.Decoder.XORKeyStream(p, p)
}
// 封裝為reader
reader := packet.Reader(p)
// 讀客戶端數據包序列號(1,2,3...)
// 客戶端發送的數據包必須包含一個自增的序號,必須嚴格遞增
// 加密後,可避免重放攻擊-REPLAY-ATTACK
seq_id, err := reader.ReadU32()
if err != nil {
log.Error("read client timestamp failed:", err)
sess.Flag |= SESS_KICKED_OUT
return nil
}
// 數據包序列號驗證
if seq_id != sess.PacketCount {
log.Errorf("illegal packet sequence id:%v should be:%v size:%v", seq_id, sess.PacketCount, len(p)-6)
sess.Flag |= SESS_KICKED_OUT
return nil
}
// 讀協議號
b, err := reader.ReadS16()
if err != nil {
log.Error("read protocol number failed.")
sess.Flag |= SESS_KICKED_OUT
return nil
}
// 根據協議號斷做服務劃分
// 協議號的劃分采用分割協議區間, 用戶可以自定義多個區間,用於轉發到不同的後端服務
var ret []byte
if b > MAX_PROTO_NUM {
if err := forward(sess, p[4:]); err != nil {
log.Errorf("service id:%v execute failed, error:%v", b, err)
sess.Flag |= SESS_KICKED_OUT
return nil
}
} else {
if h := client_handler.Handlers[b]; h != nil {
ret = h(sess, reader)
} else {
log.Errorf("service id:%v not bind", b)
sess.Flag |= SESS_KICKED_OUT
return nil
}
}
// 監控協議處理時間
// 監控數值會發送到statsd,格式為:
// API.XXX_REQ = 10ms
elasped := time.Now().Sub(start)
if b != 0 { // 排除心跳包日誌
log.Trace("[REQ]", client_handler.RCode[b])
_statter.Timing(1.0, fmt.Sprintf("%v%v", STATSD_PREFIX, client_handler.RCode[b]), elasped)
}
return ret
}
示例14: handleClient
// PIPELINE #1: handleClient
// the goroutine is used for reading incoming PACKETS
// each packet is defined as :
// | 2B size | DATA |
//
func handleClient(conn *net.TCPConn) {
defer utils.PrintPanicStack()
// set socket read buffer
conn.SetReadBuffer(SO_RCVBUF)
// set socket write buffer
conn.SetWriteBuffer(SO_SNDBUF)
// for reading the 2-Byte header
header := make([]byte, 2)
// the input channel for agent()
in := make(chan []byte)
defer func() {
close(in) // session will close
}()
// create a new session object for the connection
// and record it's IP address
var sess Session
host, port, err := net.SplitHostPort(conn.RemoteAddr().String())
if err != nil {
log.Error("cannot get remote address:", err)
return
}
sess.IP = net.ParseIP(host)
log.Infof("new connection from:%v port:%v", host, port)
// session die signal, will be triggered by agent()
sess.Die = make(chan struct{})
// create a write buffer
out := new_buffer(conn, sess.Die)
go out.start()
// start agent for PACKET processing
wg.Add(1)
go agent(&sess, in, out)
// read loop
for {
// solve dead link problem:
// physical disconnection without any communcation between client and server
// will cause the read to block FOREVER, so a timeout is a rescue.
conn.SetReadDeadline(time.Now().Add(TCP_READ_DEADLINE * time.Second))
// read 2B header
n, err := io.ReadFull(conn, header)
if err != nil {
log.Warningf("read header failed, ip:%v reason:%v size:%v", sess.IP, err, n)
return
}
size := binary.BigEndian.Uint16(header)
// alloc a byte slice of the size defined in the header for reading data
payload := make([]byte, size)
n, err = io.ReadFull(conn, payload)
if err != nil {
log.Warningf("read payload failed, ip:%v reason:%v size:%v", sess.IP, err, n)
return
}
// deliver the data to the input queue of agent()
select {
case in <- payload: // payload queued
case <-sess.Die:
log.Warningf("connection closed by logic, flag:%v ip:%v", sess.Flag, sess.IP)
return
}
}
}
示例15: agent
func agent(sess *Session, in chan []byte, out *Buffer, sess_die chan bool) {
defer wg.Done()
defer utils.PrintPanicStack()
// init session
//存儲玩家異步消息, 讓消息超過時, 會阻塞,等待等讀取,
//那麽如果一直是滿的時,玩家好久沒上線
//別的玩家發過來的消息會一直發送不過去, 這時會長期阻塞,怎麽解決, 發送方設置超時,當許久沒發送成功後,彈出對方信箱已滿?
// ...... 這裏是異步消息,還是離線消息?
sess.MQ = make(chan []byte, DEFAULT_MQ_SIZE)
sess.ConnectTime = time.Now()
sess.LastPacketTime = time.Now()
// minute timer
min_timer := time.After(time.Minute)
// cleanup work
defer func() {
close(sess_die)
// 當session關閉時,連接遊戲後段的流需要關閉
if sess.Stream != nil {
sess.Stream.CloseSend()
}
}()
// >> the main message loop <<
for {
select {
case msg, ok := <-in: // packet from network
if !ok {
return
}
//數據包個數++
sess.PacketCount++
//更新接收數據包的時間
sess.PacketTime = time.Now()
//處理用戶請求
if result := proxy_user_request(sess, msg); result != nil {
//將結果發送出去
out.send(sess, result)
}
//當處理完之後,將數據包時間設置成上個數據包時間
sess.LastPacketTime = sess.PacketTime
//如果異步通道有消息? (內部發送過來的消息)
case frame := <-sess.MQ:
switch frame.Type {
case spp.Game_Message:
out.send(sess, frame.Message)
//如果是關閉命令, 則設置關閉狀態, (用於後台管理)
case spp.Game_Kick:
sess.Flag |= SESS_KICKED_OUT
}
case <-min_timer: //minutes timer
//定時器工作, 用於檢測用戶行為,防治玩家作弊
timer_work(sess, out)
min_timer = time.After(time.Minute)
case <-die: // server is shuting down...
sess.Flag |= SESS_KICKED_OUT
}
// see if the player should be kicked out.
if sess.Flag&SESS_KICKED_OUT != 0 {
return
}
}
}