electron / electron/forge

Installed native module is not executable

Open
#3,196 0 comments 0 reactions 0 assignees View on GitHub
bug native-modules
Dominant language
TypeScript
Stars
7.1k
Forks
641
Avg merge
3d 1h
Merged PRs (30d)
30

Description

### Pre-flight checklist

- [X] I have read the [contribution documentation](https://github.com/electron/forge/blob/main/CONTRIBUTING.md) for this project.
- [X] I agree to follow the [code of conduct](https://github.com/electron/electron/blob/main/CODE_OF_CONDUCT.md) that this project uses.
- [X] I have searched the issue tracker for a bug that matches the one I want to file, without success.

### Electron Forge version

6.0.5

### Electron version

v23.1.4

### Operating system

MacOS 13.0 (ARM)

### Last known working Electron Forge version

_No response_

### Expected behavior

I want to extract 7-zip archives using the native module [7zip-min](https://github.com/onikienko/7zip-min).
Expected behaviour: Archive contents are extracted without error.

### Actual behavior

### behavior
Extracting works fine when running it outside of Electron (e.g. `yarn run ts-node src/test.ts`, see example below for code),
but it fails when triggering it from the renderer thread via `ipcRenderer.invoke`:
```
Error occurred in handler for 'run-custom-operation': Error: spawn /Users/me/my-project/.webpack/main/native_modules/mac/arm64/7za EACCES
```

### observation
- The file in question (`.webpack/main/native_modules/mac/arm64/7za`) is owned by `root` and not executable.
- Everything works fine when I first run `yarn start` and wait until the dev server is fully running, then run `chmod +x` on the file
- Running `yarn start` again will reset permissions on the file

### Steps to reproduce

## steps

1. Set up Electron Forge project via [Webpack + Typescript template](https://www.electronforge.io/templates/typescript-+-webpack-template)
2. Install [7zip-min](https://github.com/onikienko/7zip-min)
3. Add code to invoke `_7z.unpack()` (see below)
4. `yarn start`
3. invoke native module operations via `ipcRenderer.invoke` in code, e.g. on click

## code examples
### failing example

```ts
// extract.ts
const extract = async (filePath: string) => {
const osTmpDir = os.tmpdir()
const tmpDir = await fs.promises.mkdtemp(joinPaths(osTmpDir, 'random-tmp'))

return new Promise((resolve, reject) => {
_7z.unpack(filePath, tmpDir, err => {
if (err) return reject(err)
resolve(tmpDir)
})
})
}

// in index.ts
ipcMain.handle('extract', (_: IpcMainInvokeEvent, filePath: string) =>
extract(filePath)
)

// in preload.js
contextBridge.exposeInMainWorld('electronAPI', {
extract: (filePath: string) => ipcRenderer.invoke('extract', filePath),
})

// in web app (e.g. in button click handler)
await window.electronAPI.extract('path/to/archive.7z')
```

### working separate example (without Electron involved, run `yarn run ts-node src/test.ts`)
```ts
import _7z from '7zip-min'

const main = async () => {
return new Promise((resolve, reject) => {
_7z.unpack('arbitrary_file.7z', 'arbitrary_dir', err => {
if (err) return reject(err)
resolve()
})
})
}

main()
```

### Additional information

_No response_

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.