18
18
package gnet
19
19
20
20
import (
21
- "io "
21
+ "errors "
22
22
"runtime"
23
23
24
- "golang.org/x/sys/unix"
25
-
26
24
"github.com/panjf2000/gnet/v2/internal/netpoll"
27
- "github.com/panjf2000/gnet/v2/pkg/errors"
25
+ errorx "github.com/panjf2000/gnet/v2/pkg/errors"
28
26
)
29
27
30
28
func (el * eventloop ) rotate () error {
@@ -34,7 +32,7 @@ func (el *eventloop) rotate() error {
34
32
}
35
33
36
34
err := el .poller .Polling (el .accept0 )
37
- if err == errors .ErrEngineShutdown {
35
+ if errors . Is ( err , errorx .ErrEngineShutdown ) {
38
36
el .getLogger ().Debugf ("main reactor is exiting in terms of the demand from user, %v" , err )
39
37
err = nil
40
38
} else if err != nil {
@@ -52,57 +50,16 @@ func (el *eventloop) orbit() error {
52
50
defer runtime .UnlockOSThread ()
53
51
}
54
52
55
- err := el .poller .Polling (func (fd int , ev netpoll.IOEvent , _ netpoll.IOFlags ) error {
53
+ err := el .poller .Polling (func (fd int , ev netpoll.IOEvent , flags netpoll.IOFlags ) error {
56
54
c := el .connections .getConn (fd )
57
55
if c == nil {
58
56
// Somehow epoll notified with an event for a stale fd that is not in our connection set.
59
57
// We need to delete it from the epoll set.
60
58
return el .poller .Delete (fd )
61
59
}
62
-
63
- // First check for any unexpected non-IO events.
64
- // For these events we just close the corresponding connection directly.
65
- if ev & netpoll .ErrEvents != 0 && ev & unix .EPOLLIN == 0 && ev & unix .EPOLLOUT == 0 {
66
- c .outboundBuffer .Release () // don't bother to write to a connection with some unknown error
67
- return el .close (c , io .EOF )
68
- }
69
- // Secondly, check for EPOLLOUT before EPOLLIN, the former has a higher priority
70
- // than the latter regardless of the aliveness of the current connection:
71
- //
72
- // 1. When the connection is alive and the system is overloaded, we want to
73
- // offload the incoming traffic by writing all pending data back to the remotes
74
- // before continuing to read and handle requests.
75
- // 2. When the connection is dead, we need to try writing any pending data back
76
- // to the remote and close the connection first.
77
- //
78
- // We perform eventloop.write for EPOLLOUT because it will take good care of either case.
79
- if ev & (unix .EPOLLOUT | unix .EPOLLERR ) != 0 {
80
- if err := el .write (c ); err != nil {
81
- return err
82
- }
83
- }
84
- // Check for EPOLLIN before EPOLLRDHUP in case that there are pending data in
85
- // the socket buffer.
86
- if ev & (unix .EPOLLIN | unix .EPOLLERR ) != 0 {
87
- if err := el .read (c ); err != nil {
88
- return err
89
- }
90
- }
91
- // Ultimately, check for EPOLLRDHUP, this event indicates that the remote has
92
- // either closed connection or shut down the writing half of the connection.
93
- if ev & unix .EPOLLRDHUP != 0 && c .opened {
94
- if ev & unix .EPOLLIN == 0 { // unreadable EPOLLRDHUP, close the connection directly
95
- return el .close (c , io .EOF )
96
- }
97
- // Received the event of EPOLLIN | EPOLLRDHUP, but the previous eventloop.read
98
- // failed to drain the socket buffer, so we make sure we get it done this time.
99
- c .isEOF = true
100
- return el .read (c )
101
- }
102
- return nil
60
+ return c .processIO (fd , ev , flags )
103
61
})
104
-
105
- if err == errors .ErrEngineShutdown {
62
+ if errors .Is (err , errorx .ErrEngineShutdown ) {
106
63
el .getLogger ().Debugf ("event-loop(%d) is exiting in terms of the demand from user, %v" , el .idx , err )
107
64
err = nil
108
65
} else if err != nil {
@@ -130,52 +87,10 @@ func (el *eventloop) run() error {
130
87
// Somehow epoll notified with an event for a stale fd that is not in our connection set.
131
88
// We need to delete it from the epoll set.
132
89
return el .poller .Delete (fd )
133
-
134
- }
135
-
136
- // First check for any unexpected non-IO events.
137
- // For these events we just close the corresponding connection directly.
138
- if ev & netpoll .ErrEvents != 0 && ev & unix .EPOLLIN == 0 && ev & unix .EPOLLOUT == 0 {
139
- c .outboundBuffer .Release () // don't bother to write to a connection with some unknown error
140
- return el .close (c , io .EOF )
141
- }
142
- // Secondly, check for EPOLLOUT before EPOLLIN, the former has a higher priority
143
- // than the latter regardless of the aliveness of the current connection:
144
- //
145
- // 1. When the connection is alive and the system is overloaded, we want to
146
- // offload the incoming traffic by writing all pending data back to the remotes
147
- // before continuing to read and handle requests.
148
- // 2. When the connection is dead, we need to try writing any pending data back
149
- // to the remote and close the connection first.
150
- //
151
- // We perform eventloop.write for EPOLLOUT because it will take good care of either case.
152
- if ev & (unix .EPOLLOUT | unix .EPOLLERR ) != 0 {
153
- if err := el .write (c ); err != nil {
154
- return err
155
- }
156
90
}
157
- // Check for EPOLLIN before EPOLLRDHUP in case that there are pending data in
158
- // the socket buffer.
159
- if ev & (unix .EPOLLIN | unix .EPOLLERR ) != 0 {
160
- if err := el .read (c ); err != nil {
161
- return err
162
- }
163
- }
164
- // Ultimately, check for EPOLLRDHUP, this event indicates that the remote has
165
- // either closed connection or shut down the writing half of the connection.
166
- if ev & unix .EPOLLRDHUP != 0 && c .opened {
167
- if ev & unix .EPOLLIN == 0 { // unreadable EPOLLRDHUP, close the connection directly
168
- return el .close (c , io .EOF )
169
- }
170
- // Received the event of EPOLLIN | EPOLLRDHUP, but the previous eventloop.read
171
- // failed to drain the socket buffer, so we make sure we get it done this time.
172
- c .isEOF = true
173
- return el .read (c )
174
- }
175
- return nil
91
+ return c .processIO (fd , ev , flags )
176
92
})
177
-
178
- if err == errors .ErrEngineShutdown {
93
+ if errors .Is (err , errorx .ErrEngineShutdown ) {
179
94
el .getLogger ().Debugf ("event-loop(%d) is exiting in terms of the demand from user, %v" , el .idx , err )
180
95
err = nil
181
96
} else if err != nil {
0 commit comments