summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2026-08-22 00:07:00 +0800
committerruki <[email protected]>2026-08-22 00:07:00 +0800
commit8204558c513dd3e7c0b3d754435539a941bdee8e (patch)
tree6d035a8482356df23c3e6eacca9a3f45cde6856b
parent780159d6946115b89bb4657856fba361e79a1555 (diff)
improve core
-rw-r--r--core/src/xmake/utf8/width.c6
-rw-r--r--xmake/core/base/poller.lua16
-rw-r--r--xmake/core/base/scheduler.lua14
3 files changed, 27 insertions, 9 deletions
diff --git a/core/src/xmake/utf8/width.c b/core/src/xmake/utf8/width.c
index 615572462..fb79ee198 100644
--- a/core/src/xmake/utf8/width.c
+++ b/core/src/xmake/utf8/width.c
@@ -33,7 +33,11 @@
* utf8.width(codepoint)
*/
tb_int_t xm_utf8_width(lua_State* lua) {
- if (lua_isnumber(lua, 1)) {
+ /* we must not use lua_isnumber() here: it also accepts a numeric string,
+ * so utf8.width("9") would return the width of the code point 9 (a tab)
+ * instead of the width of the string "9"
+ */
+ if (lua_type(lua, 1) == LUA_TNUMBER) {
xm_utf8_int_t val = (xm_utf8_int_t)lua_tointeger(lua, 1);
lua_pushinteger(lua, xm_utf8_charwidth(val));
} else {
diff --git a/xmake/core/base/poller.lua b/xmake/core/base/poller.lua
index bb18dfda4..43c3bea1a 100644
--- a/xmake/core/base/poller.lua
+++ b/xmake/core/base/poller.lua
@@ -124,7 +124,7 @@ function poller:remove(obj)
end
-- remove poller object data
- self:_pollerdata_set(obj, nil)
+ self:_pollerdata_set(obj:cdata(), nil)
return true
end
@@ -153,13 +153,15 @@ function poller:wait(timeout)
local otype = v[1]
local cdata = v[2]
local events = v[3]
- local pollerdata = self:_pollerdata(cdata)
- if not pollerdata then
- return -1, string.format("no object data for cdata(%s)!", cdata)
+ -- this object may have been removed from the poller while its event
+ -- was already collected, e.g. a pending overlapped io on windows,
+ -- we just drop it, it has no owner any more, @see poller:remove()
+ local pollerdata = self:_pollerdata(cdata)
+ if pollerdata then
+ local obj = pollerdata[1]
+ assert(obj and obj:otype() == otype and obj:cdata() == cdata)
+ table.insert(results, {obj, events, pollerdata[2]})
end
- local obj = pollerdata[1]
- assert(obj and obj:otype() == otype and obj:cdata() == cdata)
- table.insert(results, {obj, events, pollerdata[2]})
end
end
return count, results
diff --git a/xmake/core/base/scheduler.lua b/xmake/core/base/scheduler.lua
index a59c38207..4ae8d74e0 100644
--- a/xmake/core/base/scheduler.lua
+++ b/xmake/core/base/scheduler.lua
@@ -304,9 +304,17 @@ end
function scheduler:_poller_events_cb(obj, events)
-- get poller object data
+ --
+ -- the object may have been cancelled while its event was already queued,
+ -- e.g. a process which exits right after we stopped waiting for it,
+ -- @see scheduler:poller_cancel()
+ --
+ -- such an event has no owner any more, we just drop it: it is not an
+ -- error of the scheduler and it must not abort the whole loop
local pollerdata = self:_poller_data(obj)
if not pollerdata then
- return false, string.format("%s: cannot get poller data!", obj)
+ utils.dprint("%s: drop the event(%d), it has been cancelled!", obj, events)
+ return true
end
-- is process/fwatcher object?
@@ -1068,6 +1076,10 @@ function scheduler:poller_waitproc(obj, timeout)
running:waitobj_set(obj)
-- wait
+ --
+ -- @note we keep this process in the poller if it is timeout, so its exit status
+ -- is still saved as a pending status when it exits later, and the next wait
+ -- returns it immediately, @see scheduler:_poller_events_cb()
local ok = self:co_suspend()
return ok, pollerdata.object_event
end