Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bun install segfault in Docker #9924

Open
Zananok opened this issue Apr 4, 2024 · 7 comments
Open

Bun install segfault in Docker #9924

Zananok opened this issue Apr 4, 2024 · 7 comments
Labels
bug Something isn't working docker An issue that occurs when running in Docker

Comments

@Zananok
Copy link

Zananok commented Apr 4, 2024

Now cross-posted with vue-demi: vueuse/vue-demi#259

What version of Bun is running?

1.1.0+5903a6141

What platform is your computer?

DockerImage: oven/bun:latest

What steps can reproduce the bug?

  1. Locally on wsl (PRETTY_NAME="Debian GNU/Linux 12 (bookworm)") run: bunx nuxi init my-nuxt-app (with bun 1.1.0+5903a6141) to generate a clean Nuxt app (according to https://bun.sh/guides/ecosystem/nuxt)

  2. Rsync to remote vm (also PRETTY_NAME="Debian GNU/Linux 12 (bookworm)")

  3. Remove node_modules folder (in the remote)

  4. Add the folder of the project as a mapped volume (so, not copying it into the docker, just mapping it from the host) in docker-compose.yml:

version "3.8":
...
    image: oven/bun
    ulimits:
      rtprio: 95
      memlock: -1
    volumes:
      - '/apps/${containerName}/data-root/nuxt-dev:/app:z'
  1. Either from entrypoint or from inside the docker in the workdir /app: bun --revision && bun install && bun dev
    NB: error occurs on bun install.

Result:

1.1.0+5903a6141
2024-04-04T09:00:16.627756172Z bun install v1.1.0 (5903a61)
2024-04-04T09:00:33.889355055Z error: postinstall script from "vue-demi" terminated by SIGSEGV (Address boundary error)
2024-04-04T09:00:40.747806045Z Segmentation fault (core dumped)

Running bun install and bun dev locally on wsl works. Bun used in wsl is for linux/debian, not for windows.
Same error when running it on bun v1.0.33. When v1.1 came out, I hoped this was fixed, but no dice.

What is the expected behavior?

Work successfully, just like when its ran in wsl.

What do you see instead?

image

1.1.0+5903a6141
2024-04-04T09:00:16.627756172Z bun install v1.1.0 (5903a61)
2024-04-04T09:00:33.889355055Z error: postinstall script from "vue-demi" terminated by SIGSEGV (Address boundary error)
2024-04-04T09:00:40.747806045Z Segmentation fault (core dumped)

During the brief moment that bun install runs (reaching up to about 114%):
8GiB:
image
16GiB:
image

The VM this docker is running on has 8 dedicated cores (16 threads). Tried with the VM's original 8GiB ram, then upgraded to 16GiB ram. Same result.

Additional information

Tried in a complete clean scenario, and steps provided is for a clean scenario.
I took notice of this issue when trying to convert/run an existing working nuxt3 pnpm project, and on my steps of debugging, I decided to try clean project.

The above steps will work in docker if used with npm/yarn/pnpm once the node_modules is deleted.
The Debian VM is using the same CPU (AMD Ryzen Threadripper 3990X 64-Core, 128-Thread) as the wsl v1 under a Windows 11 VM, as both are on the same machine.
Both wsl and the debian VM are running latest debian image, while no docker is installed on the windows/wsl, the one on the debian VM was updated to the latest to confirm that its not due to old docker package.

Debian VM extra info:
docker --version: Docker version 26.0.0, build 2ae903e
uname -r (Kernel): 6.1.0-18-amd64

The VM this docker is running on has 8 dedicated cores (16 threads). Tried with the VM's original 8GiB ram, then upgraded to 16GiB ram. Same result.

Between each test and variations of tests, I rm -rf node-modules and down && up --build to be sure it was as clean as possible.

Additional logs and attempts:

bun --revision && bun install --ignore-scripts && bun dev:
image

perf --version: perf version 5.10.209

bun --revision && perf trace bun install -y && bun dev: perf-trace.nuxt-dev.log.zip (ZIP as the .log is 26.3 MB)

bun --revision && perf trace bun install -y && perf trace bun dev: perf-trace.nuxt-dev-install_and_dev.log.zip (log: 29.3 MB)

@Zananok Zananok added the bug Something isn't working label Apr 4, 2024
@Jarred-Sumner
Copy link
Collaborator

What Linux kernel version is in use on the VM?

@Zananok
Copy link
Author

Zananok commented Apr 4, 2024

Updated original post with the kernel information:
uname -r (Kernel): 6.1.0-18-amd64

@Jarred-Sumner
Copy link
Collaborator

Hm. Can you try perf trace bun install and paste the output? I'm wondering what system calls are being used shortly before it segfaults.

Another thing you could try: can you run bun install --ignore-scripts? I want to rule out whether or not it's related to postinstall scripts being run

Are there any unusual permission configurations being set? Is vfork allowed?

@Zananok
Copy link
Author

Zananok commented Apr 4, 2024

I will do the perf trace soon and update the main topic, but the --ignore-scripts will work, but subsequently print the same error when running bun dev.

Edit: updated with both results.

Edit2: no, there are no 'unusual' settings being set on docker-compose, other than privileged: true and mounted volume: /sys/kernel/debug:/sys/kernel/debug:rw,nosuid,nodev,noexec,relatime for to be able to run perf. Originally these were not there. My other "settings" that I didn't post in the original post are: the port open (singular), timezone (Norway) and working dir: /app.

edit3: perf --version: perf version 5.10.209

@Jarred-Sumner
Copy link
Collaborator

It appears that it is segfaulting on process start

 13818.593 ( 0.007 ms): bun/3061 fstat(fd: 116</memfd:spawn_stdio_stdout (deleted)>, statbuf: 0x7ffdd1e11ac0) = 0
 13818.606 ( 0.006 ms): bun/3061 pread64(fd: 116</memfd:spawn_stdio_stdout (deleted)>, buf: 0x4bcd8272180, count: 20) = 0
 13818.619 ( 0.005 ms): bun/3061 sched_getaffinity(len: 128, user_mask_ptr: 0x7ffdd1e11a98)            = 8
 13818.633 ( 0.023 ms): bun/3061 mmap(len: 4198400, flags: PRIVATE|ANONYMOUS|STACK)                    = 0x7f229e3f9000
 13818.662 ( 0.012 ms): bun/3061 mprotect(start: 0x7f229e3fa000, len: 4194304, prot: READ|WRITE)       = 0
error: postinstall script from "vue-demi" terminated by SIGSEGV (Address boundary error)
 13819.469 ( 0.252 ms): bun/3061 clone(clone_flags: VM|FS|FILES|SIGHAND|THREAD|SYSVSEM|SETTLS|PARENT_SETTID|CHILD_CLEARTID, newsp: 0x7f229e79d370, parent_tidptr: 0x7f229e7f99d0, child_tidptr: 0x7f229e7f99d0, tls: 0x7f229e7f9700) = 3109 (bun)
 13819.728 ( 0.004 ms): bun/3061 fstat(fd: 117</memfd:spawn_stdio_stderr (deleted)>, statbuf: 0x7ffdd1e11ac0) = 0
 13819.734 ( 0.004 ms): bun/3061 pread64(fd: 117</memfd:spawn_stdio_stderr (deleted)>, buf: 0x4bcd8272180, count: 20) = 0
 13819.752 ( 0.008 ms): bun/3061 write(fd: 2<pipe:[54635]>, buf: 0x7f22cf5853a4, count: 89)            = 89
 13819.763 ( 0.003 ms): bun/3061 rt_sigaction(sig: SEGV, act: 0x7ffdd1e11a70, sigsetsize: 8)           = 0
 15589.572 ( 0.009 ms): bun/3060 pread64(fd: 18</memfd:spawn_stdio_stdout (deleted)>, buf: 0x58e40272d80, count: 20) = 0
 15589.597 ( 0.014 ms): bun/3060 sched_getaffinity(len: 128, user_mask_ptr: 0x7ffc6548ab98)            = 8
 15589.624 ( 0.029 ms): bun/3060 mmap(len: 4198400, flags: PRIVATE|ANONYMOUS|STACK)                    = 0x7f08153f5000
 15589.663 ( 0.018 ms): bun/3060 mprotect(start: 0x7f08153f6000, len: 4194304, prot: READ|WRITE)       = 0
error: postinstall script from "vue-demi" terminated by SIGSEGV (Address boundary error)
 15589.936 ( 0.289 ms): bun/3060 clone(clone_flags: VM|FS|FILES|SIGHAND|THREAD|SYSVSEM|SETTLS|PARENT_SETTID|CHILD_CLEARTID, newsp: 0x7f0815799370, parent_tidptr: 0x7f08157f59d0, child_tidptr: 0x7f08157f59d0, tls: 0x7f08157f5700) = 3107 (bun)
 15590.239 ( 0.004 ms): bun/3060 fstat(fd: 119</memfd:spawn_stdio_stderr (deleted)>, statbuf: 0x7ffc6548abc0) = 0
 15590.246 ( 0.004 ms): bun/3060 pread64(fd: 119</memfd:spawn_stdio_stderr (deleted)>, buf: 0x58e40272d80, count: 20) = 0
 15590.273 ( 0.013 ms): bun/3060 write(fd: 2<pipe:[52255]>, buf: 0x7f08364ea3a4, count: 89)            = 89
 15590.290 ( 0.003 ms): bun/3060 rt_sigaction(sig: SEGV, act: 0x7ffc6548ab70, sigsetsize: 8)           = 0

@Zananok
Copy link
Author

Zananok commented Apr 5, 2024

I don't mean that we should debug some else's library in a bun bug report, however, segfault of a js running in bun seems like its not the error that should occur if someone programmed a postinstall that does not take into account bun. Additionally, from the v1.1 video, it was recommended to report any "libraries" that didn't work in bun if they worked in npm. Strangely, it does work on WSL, as aforementioned, and it does work on docker using pnpm. For the record, I have also tried a debian:latest dockerfile with the curl -fsSL https://bun.sh/install | bash (resulting in the same segfault issue), so I assume there is no specific issue with oven/bun:latest.

Edit: My suspicion of the cause of the error is this code on utils.

// unlink for pnpm, #92
  try {
    fs.unlinkSync(dest)
  } catch (error) { }
  fs.writeFileSync(dest, content, 'utf-8')

Here is the source code of the files in question:

node_modules/vue-demi/scripts/postinstall.js

const { switchVersion, loadModule } = require('./utils')

const Vue = loadModule('vue')

if (!Vue || typeof Vue.version !== 'string') {
  console.warn('[vue-demi] Vue is not found. Please run "npm install vue" to install.')
}
else if (Vue.version.startsWith('2.7.')) {
  switchVersion(2.7)
}
else if (Vue.version.startsWith('2.')) {
  switchVersion(2)
}
else if (Vue.version.startsWith('3.')) {
  switchVersion(3)
}
else {
  console.warn(`[vue-demi] Vue version v${Vue.version} is not suppported.`)
}

node_modules/vue-demi/scripts/utils.js

const fs = require('fs')
const path = require('path')

const dir = path.resolve(__dirname, '..', 'lib')

function loadModule(name) {
  try {
    return require(name)
  } catch (e) {
    return undefined
  }
}

function copy(name, version, vue) {
  vue = vue || 'vue'
  const src = path.join(dir, `v${version}`, name)
  const dest = path.join(dir, name)
  let content = fs.readFileSync(src, 'utf-8')
  content = content.replace(/'vue'/g, `'${vue}'`)
  // unlink for pnpm, #92
  try {
    fs.unlinkSync(dest)
  } catch (error) { }
  fs.writeFileSync(dest, content, 'utf-8')
}

function updateVue2API() {
  const ignoreList = ['version', 'default']
  const VCA = loadModule('@vue/composition-api')
  if (!VCA) {
    console.warn('[vue-demi] Composition API plugin is not found. Please run "npm install @vue/composition-api" to install.')
    return
  }

  const exports = Object.keys(VCA).filter(i => !ignoreList.includes(i))

  const esmPath = path.join(dir, 'index.mjs')
  let content = fs.readFileSync(esmPath, 'utf-8')

  content = content.replace(
    /\/\*\*VCA-EXPORTS\*\*\/[\s\S]+\/\*\*VCA-EXPORTS\*\*\//m,
`/**VCA-EXPORTS**/
export { ${exports.join(', ')} } from '@vue/composition-api/dist/vue-composition-api.mjs'
/**VCA-EXPORTS**/`
    )

  fs.writeFileSync(esmPath, content, 'utf-8')

}

function switchVersion(version, vue) {
  copy('index.cjs', version, vue)
  copy('index.mjs', version, vue)
  copy('index.d.ts', version, vue)

  if (version === 2)
    updateVue2API()
}


module.exports.loadModule = loadModule
const fs = require('fs')
const path = require('path')

const dir = path.resolve(__dirname, '..', 'lib')

function loadModule(name) {
  try {
    return require(name)
  } catch (e) {
    return undefined
  }
}

function copy(name, version, vue) {
  vue = vue || 'vue'
  const src = path.join(dir, `v${version}`, name)
  const dest = path.join(dir, name)
  let content = fs.readFileSync(src, 'utf-8')
  content = content.replace(/'vue'/g, `'${vue}'`)
  // unlink for pnpm, #92
  try {
    fs.unlinkSync(dest)
  } catch (error) { }
  fs.writeFileSync(dest, content, 'utf-8')
}

function updateVue2API() {
  const ignoreList = ['version', 'default']
  const VCA = loadModule('@vue/composition-api')
  if (!VCA) {
    console.warn('[vue-demi] Composition API plugin is not found. Please run "npm install @vue/composition-api" to install.')
    return
  }

  const exports = Object.keys(VCA).filter(i => !ignoreList.includes(i))

  const esmPath = path.join(dir, 'index.mjs')
  let content = fs.readFileSync(esmPath, 'utf-8')

  content = content.replace(
    /\/\*\*VCA-EXPORTS\*\*\/[\s\S]+\/\*\*VCA-EXPORTS\*\*\//m,
`/**VCA-EXPORTS**/
export { ${exports.join(', ')} } from '@vue/composition-api/dist/vue-composition-api.mjs'
/**VCA-EXPORTS**/`
    )

  fs.writeFileSync(esmPath, content, 'utf-8')

}

function switchVersion(version, vue) {
  copy('index.cjs', version, vue)
  copy('index.mjs', version, vue)
  copy('index.d.ts', version, vue)

  if (version === 2)
    updateVue2API()
}


module.exports.loadModule = loadModule
module.exports.switchVersion = switchVersion

@Zananok
Copy link
Author

Zananok commented Apr 5, 2024

I noticed now that once running bun install a second time, without cleaning up the env, another error occurs. Subsequent calls to bun just repeats the last error:

root@b0eae7d7ecee:/app# bun install
bun install v1.1.0 (5903a614)
  🚚 prompts... error: postinstall script from "vue-demi" terminated by SIGSEGV (Address boundary error)
Segmentation fault (core dumped)
root@b0eae7d7ecee:/app# bun install
bun install v1.1.0 (5903a614)

$ nuxt prepare
error: postinstall script from "nuxt-app" terminated by SIGSEGV (Address boundary error)
Segmentation fault (core dumped)
root@b0eae7d7ecee:/app# bun install
bun install v1.1.0 (5903a614)

$ nuxt prepare
error: postinstall script from "nuxt-app" terminated by SIGSEGV (Address boundary error)
Segmentation fault (core dumped)

Though I can't seem to find it's postinstall script:

❯ find . -iname "postinstall*"
./node_modules/vue-demi/scripts/postinstall.js

@Electroid Electroid added the docker An issue that occurs when running in Docker label Apr 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working docker An issue that occurs when running in Docker
Projects
None yet
Development

No branches or pull requests

3 participants