10

lua-socket imcompatbility with Lua 5.4.3 and the fixup

 2 years ago
source link: https://ttys3.dev/post/lua-socket-imcompatbility-with-lua-543-and-the-fixup/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

October 20, 2021

the problem

lua 版本: Lua 5.4.3 Copyright (C) 1994-2021 Lua.org, PUC-Rio

相关 issue HTTP calls do not work with lua 5.4.3 #331

socket/http.lua:54: bad argument #1 to 'receive' (string expected, got light userdata)

the solution

有人已经提交一个 PR 了: https://github.com/diegonehab/luasocket/pull/334

根据这个 PR 的 review comment 来看, 貌似是这个提交漏改了一处: https://github.com/diegonehab/luasocket/commit/f329aae724573b87bd2a814f4858d29ca894600b

luarocks 其实是变相地支持从 git 仓库安装 rocks 的.

不过我测试 luarocks install https://example.com/xxxx.spec 失败了, 报的是网络问题, 但是实际上我用 curl 请求是成功的, 不太清楚原因. 因此只好把 spec 文件下载回来再 install.

https://github.com/diegonehab/luasocket/blob/master/rockspec/luasocket-scm-2.rockspec 修改一下:

ersion = "scm-3"
source = {
  url = "git://github.com/pkulchenko/luasocket.git"
  , branch="lua-543-aux-buffer-fix"
}

我把修改后的结果直接放 gist 了, 安装:

cd /tmp/ && curl -LO https://gist.github.com/ttys3/31dbf88ee7d708294d8ae5b0a4954424/raw/c74afc3edc1a48c0f7e1c2c9992750301bbb74ff/luasocket-scm-3.rockspec
luarocks install ./luasocket-scm-3.rockspec

这样安装成功后, 发现还是报同样的错. 然后发现是通过 pacman 安装了 lua-socket 包, 其优先级不知道为什么居然比我的 luarocks 的要高.

简单处理, 把系统的先卸载了吧, 看上去没啥其它东西依赖它:

❯ ls /usr/lib/lua/5.4/socket 
 core.so   serial.so   unix.so

 
❯ paru -R lua-socket
checking dependencies...
error: failed to prepare transaction (could not satisfy dependencies)
:: removing lua-socket breaks dependency 'lua-socket' required by lua-copas
:: removing lua-socket breaks dependency 'lua-socket' required by lua-sec
  ☸ homenas (tkn-demo) in ~/.luarocks via  v5.4.3 
🔴 1 ❯ paru -R lua-socket lua-sec lua-copas
checking dependencies...
:: luarocks optionally requires lua-sec: HTTPS support

Package (3)  Old Version  Net Change

lua-copas    2.0.2-3       -0.10 MiB
lua-sec      2:1.0.2-1     -0.19 MiB
lua-socket   20200329-1    -0.23 MiB

Total Removed Size:  0.52 MiB

暂时来说, 问题解决. 等 https://github.com/diegonehab/luasocket 发新版本修复.


what is Light Userdata ?

https://www.lua.org/pil/28.5.html

https://www.shouce.ren/api/lua/5/_161.htm

目前为止我们使用的userdata称为full userdata。Lua还提供了另一种userdata: light userdata。

一个light userdatum是一个表示C指针的值(也就是一个void *类型的值)。由于它是一个值,我们不能创建他们(同样的,我们也不能创建一个数字)。可以使用函数lua_pushlightuserdata将一个light userdatum入栈:

void lua_pushlightuserdata (lua_State *L, void *p);

尽管都是userdata,light userdata和full userdata有很大不同。Light userdata不是一个缓冲区,仅仅是一个指针,没有metatables。像数字一样,light userdata不需要垃圾收集器来管理她。

有些人把light userdata作为一个低代价的替代实现,来代替full userdata,但是这不是light userdata的典型应用。首先,使用light userdata你必须自己管理内存,因为他们和垃圾收集器无关。第二,尽管从名字上看有轻重之分,但full userdata实现的代价也并不大,比较而言,他只是在分配给定大小的内存时候,有一点点额外的代价。

Light userdata真正的用处在于可以表示不同类型的对象。当full userdata是一个对象的时候,它等于对象自身;另一方面,light userdata表示的是一个指向对象的指针,同样的,它等于指针指向的任何类型的userdata。所以,我们在Lua中使用light userdata表示C对象。

看一个典型的例子,假定我们要实现:Lua和窗口系统的绑定。这种情况下,我们使用full userdata表示窗口(每一个userdatum可以包含整个窗口结构或者一个有系统创建的指向单个窗口的指针)。当在窗口有一个事件发生(比如按下鼠标),系统会根据窗口的地址调用专门的回调函数。为了将这个回调函数传递给Lua,我们必须找到表示指定窗口的userdata。为了找到这个userdata,我们可以使用一个表:索引为表示窗口地址的light userdata,值为在Lua中表示窗口的full userdata。一旦我们有了窗口的地址,我们将窗口地址作为light userdata放到栈内,并且将userdata作为表的索引存到表内。(注意这个表应该有一个weak值,否则,这些full userdata永远不会被回收掉。)


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK