Software / code / prosody
Comparison
util-src/poll.c @ 11120:b2331f3dfeea
Merge 0.11->trunk
| author | Matthew Wild <mwild1@gmail.com> |
|---|---|
| date | Wed, 30 Sep 2020 09:50:33 +0100 |
| parent | 10921:6eb5d2bb11af |
| child | 12314:898554323338 |
comparison
equal
deleted
inserted
replaced
| 11119:68df52bf08d5 | 11120:b2331f3dfeea |
|---|---|
| 35 #endif | 35 #endif |
| 36 | 36 |
| 37 #if (LUA_VERSION_NUM == 501) | 37 #if (LUA_VERSION_NUM == 501) |
| 38 #define luaL_setmetatable(L, tname) luaL_getmetatable(L, tname); lua_setmetatable(L, -2) | 38 #define luaL_setmetatable(L, tname) luaL_getmetatable(L, tname); lua_setmetatable(L, -2) |
| 39 #endif | 39 #endif |
| 40 #if (LUA_VERSION_NUM < 504) | |
| 41 #define luaL_pushfail lua_pushnil | |
| 42 #endif | |
| 40 | 43 |
| 41 /* | 44 /* |
| 42 * Structure to keep state for each type of API | 45 * Structure to keep state for each type of API |
| 43 */ | 46 */ |
| 44 typedef struct Lpoll_state { | 47 typedef struct Lpoll_state { |
| 57 } Lpoll_state; | 60 } Lpoll_state; |
| 58 | 61 |
| 59 /* | 62 /* |
| 60 * Add an FD to be watched | 63 * Add an FD to be watched |
| 61 */ | 64 */ |
| 62 int Ladd(lua_State *L) { | 65 static int Ladd(lua_State *L) { |
| 63 struct Lpoll_state *state = luaL_checkudata(L, 1, STATE_MT); | 66 struct Lpoll_state *state = luaL_checkudata(L, 1, STATE_MT); |
| 64 int fd = luaL_checkinteger(L, 2); | 67 int fd = luaL_checkinteger(L, 2); |
| 65 | 68 |
| 66 int wantread = lua_toboolean(L, 3); | 69 int wantread = lua_toboolean(L, 3); |
| 67 int wantwrite = lua_toboolean(L, 4); | 70 int wantwrite = lua_toboolean(L, 4); |
| 68 | 71 |
| 69 if(fd < 0) { | 72 if(fd < 0) { |
| 70 lua_pushnil(L); | 73 luaL_pushfail(L); |
| 71 lua_pushstring(L, strerror(EBADF)); | 74 lua_pushstring(L, strerror(EBADF)); |
| 72 lua_pushinteger(L, EBADF); | 75 lua_pushinteger(L, EBADF); |
| 73 return 3; | 76 return 3; |
| 74 } | 77 } |
| 75 | 78 |
| 82 | 85 |
| 83 int ret = epoll_ctl(state->epoll_fd, EPOLL_CTL_ADD, fd, &event); | 86 int ret = epoll_ctl(state->epoll_fd, EPOLL_CTL_ADD, fd, &event); |
| 84 | 87 |
| 85 if(ret < 0) { | 88 if(ret < 0) { |
| 86 ret = errno; | 89 ret = errno; |
| 87 lua_pushnil(L); | 90 luaL_pushfail(L); |
| 88 lua_pushstring(L, strerror(ret)); | 91 lua_pushstring(L, strerror(ret)); |
| 89 lua_pushinteger(L, ret); | 92 lua_pushinteger(L, ret); |
| 90 return 3; | 93 return 3; |
| 91 } | 94 } |
| 92 | 95 |
| 94 return 1; | 97 return 1; |
| 95 | 98 |
| 96 #else | 99 #else |
| 97 | 100 |
| 98 if(fd > FD_SETSIZE) { | 101 if(fd > FD_SETSIZE) { |
| 99 lua_pushnil(L); | 102 luaL_pushfail(L); |
| 100 lua_pushstring(L, strerror(EBADF)); | 103 lua_pushstring(L, strerror(EBADF)); |
| 101 lua_pushinteger(L, EBADF); | 104 lua_pushinteger(L, EBADF); |
| 102 return 3; | 105 return 3; |
| 103 } | 106 } |
| 104 | 107 |
| 105 if(FD_ISSET(fd, &state->all)) { | 108 if(FD_ISSET(fd, &state->all)) { |
| 106 lua_pushnil(L); | 109 luaL_pushfail(L); |
| 107 lua_pushstring(L, strerror(EEXIST)); | 110 lua_pushstring(L, strerror(EEXIST)); |
| 108 lua_pushinteger(L, EEXIST); | 111 lua_pushinteger(L, EEXIST); |
| 109 return 3; | 112 return 3; |
| 110 } | 113 } |
| 111 | 114 |
| 135 } | 138 } |
| 136 | 139 |
| 137 /* | 140 /* |
| 138 * Set events to watch for, readable and/or writable | 141 * Set events to watch for, readable and/or writable |
| 139 */ | 142 */ |
| 140 int Lset(lua_State *L) { | 143 static int Lset(lua_State *L) { |
| 141 struct Lpoll_state *state = luaL_checkudata(L, 1, STATE_MT); | 144 struct Lpoll_state *state = luaL_checkudata(L, 1, STATE_MT); |
| 142 int fd = luaL_checkinteger(L, 2); | 145 int fd = luaL_checkinteger(L, 2); |
| 143 | 146 |
| 144 #ifdef USE_EPOLL | 147 #ifdef USE_EPOLL |
| 145 | 148 |
| 158 lua_pushboolean(L, 1); | 161 lua_pushboolean(L, 1); |
| 159 return 1; | 162 return 1; |
| 160 } | 163 } |
| 161 else { | 164 else { |
| 162 ret = errno; | 165 ret = errno; |
| 163 lua_pushnil(L); | 166 luaL_pushfail(L); |
| 164 lua_pushstring(L, strerror(ret)); | 167 lua_pushstring(L, strerror(ret)); |
| 165 lua_pushinteger(L, ret); | 168 lua_pushinteger(L, ret); |
| 166 return 3; | 169 return 3; |
| 167 } | 170 } |
| 168 | 171 |
| 169 #else | 172 #else |
| 170 | 173 |
| 171 if(!FD_ISSET(fd, &state->all)) { | 174 if(!FD_ISSET(fd, &state->all)) { |
| 172 lua_pushnil(L); | 175 luaL_pushfail(L); |
| 173 lua_pushstring(L, strerror(ENOENT)); | 176 lua_pushstring(L, strerror(ENOENT)); |
| 174 lua_pushinteger(L, ENOENT); | 177 lua_pushinteger(L, ENOENT); |
| 178 return 3; | |
| 175 } | 179 } |
| 176 | 180 |
| 177 if(!lua_isnoneornil(L, 3)) { | 181 if(!lua_isnoneornil(L, 3)) { |
| 178 if(lua_toboolean(L, 3)) { | 182 if(lua_toboolean(L, 3)) { |
| 179 FD_SET(fd, &state->wantread); | 183 FD_SET(fd, &state->wantread); |
| 198 } | 202 } |
| 199 | 203 |
| 200 /* | 204 /* |
| 201 * Remove FDs | 205 * Remove FDs |
| 202 */ | 206 */ |
| 203 int Ldel(lua_State *L) { | 207 static int Ldel(lua_State *L) { |
| 204 struct Lpoll_state *state = luaL_checkudata(L, 1, STATE_MT); | 208 struct Lpoll_state *state = luaL_checkudata(L, 1, STATE_MT); |
| 205 int fd = luaL_checkinteger(L, 2); | 209 int fd = luaL_checkinteger(L, 2); |
| 206 | 210 |
| 207 #ifdef USE_EPOLL | 211 #ifdef USE_EPOLL |
| 208 | 212 |
| 215 lua_pushboolean(L, 1); | 219 lua_pushboolean(L, 1); |
| 216 return 1; | 220 return 1; |
| 217 } | 221 } |
| 218 else { | 222 else { |
| 219 ret = errno; | 223 ret = errno; |
| 220 lua_pushnil(L); | 224 luaL_pushfail(L); |
| 221 lua_pushstring(L, strerror(ret)); | 225 lua_pushstring(L, strerror(ret)); |
| 222 lua_pushinteger(L, ret); | 226 lua_pushinteger(L, ret); |
| 223 return 3; | 227 return 3; |
| 224 } | 228 } |
| 225 | 229 |
| 226 #else | 230 #else |
| 227 | 231 |
| 228 if(!FD_ISSET(fd, &state->all)) { | 232 if(!FD_ISSET(fd, &state->all)) { |
| 229 lua_pushnil(L); | 233 luaL_pushfail(L); |
| 230 lua_pushstring(L, strerror(ENOENT)); | 234 lua_pushstring(L, strerror(ENOENT)); |
| 231 lua_pushinteger(L, ENOENT); | 235 lua_pushinteger(L, ENOENT); |
| 236 return 3; | |
| 232 } | 237 } |
| 233 | 238 |
| 234 FD_CLR(fd, &state->wantread); | 239 FD_CLR(fd, &state->wantread); |
| 235 FD_CLR(fd, &state->wantwrite); | 240 FD_CLR(fd, &state->wantwrite); |
| 236 FD_CLR(fd, &state->readable); | 241 FD_CLR(fd, &state->readable); |
| 245 | 250 |
| 246 | 251 |
| 247 /* | 252 /* |
| 248 * Check previously manipulated event state for FDs ready for reading or writing | 253 * Check previously manipulated event state for FDs ready for reading or writing |
| 249 */ | 254 */ |
| 250 int Lpushevent(lua_State *L, struct Lpoll_state *state) { | 255 static int Lpushevent(lua_State *L, struct Lpoll_state *state) { |
| 251 #ifdef USE_EPOLL | 256 #ifdef USE_EPOLL |
| 252 | 257 |
| 253 if(state->processed > 0) { | 258 if(state->processed > 0) { |
| 254 state->processed--; | 259 state->processed--; |
| 255 struct epoll_event event = state->events[state->processed]; | 260 struct epoll_event event = state->events[state->processed]; |
| 279 } | 284 } |
| 280 | 285 |
| 281 /* | 286 /* |
| 282 * Wait for event | 287 * Wait for event |
| 283 */ | 288 */ |
| 284 int Lwait(lua_State *L) { | 289 static int Lwait(lua_State *L) { |
| 285 struct Lpoll_state *state = luaL_checkudata(L, 1, STATE_MT); | 290 struct Lpoll_state *state = luaL_checkudata(L, 1, STATE_MT); |
| 286 | 291 |
| 287 int ret = Lpushevent(L, state); | 292 int ret = Lpushevent(L, state); |
| 288 | 293 |
| 289 if(ret != 0) { | 294 if(ret != 0) { |
| 310 | 315 |
| 311 ret = select(FD_SETSIZE, &state->readable, &state->writable, &state->err, &tv); | 316 ret = select(FD_SETSIZE, &state->readable, &state->writable, &state->err, &tv); |
| 312 #endif | 317 #endif |
| 313 | 318 |
| 314 if(ret == 0) { | 319 if(ret == 0) { |
| 320 /* Is this an error? */ | |
| 315 lua_pushnil(L); | 321 lua_pushnil(L); |
| 316 lua_pushstring(L, "timeout"); | 322 lua_pushstring(L, "timeout"); |
| 317 return 2; | 323 return 2; |
| 318 } | 324 } |
| 319 else if(ret < 0 && errno == EINTR) { | 325 else if(ret < 0 && errno == EINTR) { |
| 326 /* Is this an error? */ | |
| 320 lua_pushnil(L); | 327 lua_pushnil(L); |
| 321 lua_pushstring(L, "signal"); | 328 lua_pushstring(L, "signal"); |
| 322 return 2; | 329 return 2; |
| 323 } | 330 } |
| 324 else if(ret < 0) { | 331 else if(ret < 0) { |
| 325 ret = errno; | 332 ret = errno; |
| 326 lua_pushnil(L); | 333 luaL_pushfail(L); |
| 327 lua_pushstring(L, strerror(ret)); | 334 lua_pushstring(L, strerror(ret)); |
| 328 lua_pushinteger(L, ret); | 335 lua_pushinteger(L, ret); |
| 329 return 3; | 336 return 3; |
| 330 } | 337 } |
| 331 | 338 |
| 342 | 349 |
| 343 #ifdef USE_EPOLL | 350 #ifdef USE_EPOLL |
| 344 /* | 351 /* |
| 345 * Return Epoll FD | 352 * Return Epoll FD |
| 346 */ | 353 */ |
| 347 int Lgetfd(lua_State *L) { | 354 static int Lgetfd(lua_State *L) { |
| 348 struct Lpoll_state *state = luaL_checkudata(L, 1, STATE_MT); | 355 struct Lpoll_state *state = luaL_checkudata(L, 1, STATE_MT); |
| 349 lua_pushinteger(L, state->epoll_fd); | 356 lua_pushinteger(L, state->epoll_fd); |
| 350 return 1; | 357 return 1; |
| 351 } | 358 } |
| 352 | 359 |
| 353 /* | 360 /* |
| 354 * Close epoll FD | 361 * Close epoll FD |
| 355 */ | 362 */ |
| 356 int Lgc(lua_State *L) { | 363 static int Lgc(lua_State *L) { |
| 357 struct Lpoll_state *state = luaL_checkudata(L, 1, STATE_MT); | 364 struct Lpoll_state *state = luaL_checkudata(L, 1, STATE_MT); |
| 358 | 365 |
| 359 if(state->epoll_fd == -1) { | 366 if(state->epoll_fd == -1) { |
| 360 return 0; | 367 return 0; |
| 361 } | 368 } |
| 373 #endif | 380 #endif |
| 374 | 381 |
| 375 /* | 382 /* |
| 376 * String representation | 383 * String representation |
| 377 */ | 384 */ |
| 378 int Ltos(lua_State *L) { | 385 static int Ltos(lua_State *L) { |
| 379 struct Lpoll_state *state = luaL_checkudata(L, 1, STATE_MT); | 386 struct Lpoll_state *state = luaL_checkudata(L, 1, STATE_MT); |
| 380 lua_pushfstring(L, "%s: %p", STATE_MT, state); | 387 lua_pushfstring(L, "%s: %p", STATE_MT, state); |
| 381 return 1; | 388 return 1; |
| 382 } | 389 } |
| 383 | 390 |
| 384 /* | 391 /* |
| 385 * Create a new context | 392 * Create a new context |
| 386 */ | 393 */ |
| 387 int Lnew(lua_State *L) { | 394 static int Lnew(lua_State *L) { |
| 388 /* Allocate state */ | 395 /* Allocate state */ |
| 389 Lpoll_state *state = lua_newuserdata(L, sizeof(Lpoll_state)); | 396 Lpoll_state *state = lua_newuserdata(L, sizeof(Lpoll_state)); |
| 390 luaL_setmetatable(L, STATE_MT); | 397 luaL_setmetatable(L, STATE_MT); |
| 391 | 398 |
| 392 /* Initialize state */ | 399 /* Initialize state */ |
| 395 state->processed = 0; | 402 state->processed = 0; |
| 396 | 403 |
| 397 int epoll_fd = epoll_create1(EPOLL_CLOEXEC); | 404 int epoll_fd = epoll_create1(EPOLL_CLOEXEC); |
| 398 | 405 |
| 399 if(epoll_fd <= 0) { | 406 if(epoll_fd <= 0) { |
| 400 lua_pushnil(L); | 407 luaL_pushfail(L); |
| 401 lua_pushstring(L, strerror(errno)); | 408 lua_pushstring(L, strerror(errno)); |
| 402 lua_pushinteger(L, errno); | 409 lua_pushinteger(L, errno); |
| 403 return 3; | 410 return 3; |
| 404 } | 411 } |
| 405 | 412 |