Skip to content

Commit 356f98c

Browse files
authored
Merge pull request #1594 from session-foundation/chore-test-debug-crash-with-reporter
feat: add crash reporter + downgrade sharp to 0.33.3
2 parents 9243b1f + 8023471 commit 356f98c

File tree

6 files changed

+181
-148
lines changed

6 files changed

+181
-148
lines changed

package.json

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "session-desktop",
33
"productName": "Session",
44
"description": "Private messaging from your desktop",
5-
"version": "1.16.8",
5+
"version": "1.16.9",
66
"license": "GPL-3.0",
77
"author": {
88
"name": "Session Foundation",
@@ -39,7 +39,7 @@
3939
"build-release-base": "cross-env NODE_ENV=production electron-builder --config.extraMetadata.environment=production",
4040
"build-release": "yarn build-release-base --publish=never --config.directories.output=release",
4141
"build-release-publish": "yarn build-release-base --publish=always",
42-
"ready": "yarn dedup --fail && yarn build-everything && yarn lint && yarn test",
42+
"ready": "yarn dedup --fail && yarn build && yarn lint && yarn test",
4343
"postinstall": "yarn patch-package && yarn electron-builder install-app-deps",
4444
"update-git-info": "node ./build/updateLocalConfig.js",
4545
"worker:utils": "webpack --config=./utils.worker.config.js",
@@ -49,7 +49,6 @@
4949
"prepare": "husky",
5050
"print-deps": "node -v && python3 --version",
5151
"watch": "yarn clean && yarn update-git-info && concurrently -n PBJS,SASS,LOCALES,UTIL,LIBSESSION,IMAGE,TS -c yellow,green,red,blue,blue,blue,green \"yarn protobuf\" \"yarn sass --watch\" \"yarn build:locales-soft\" \"yarn worker:utils --watch\" \"yarn worker:libsession --watch\" \"yarn worker:image_processor --watch\" \"yarn tsc --watch\""
52-
5352
},
5453
"dependencies": {
5554
"@emoji-mart/data": "^1.2.1",
@@ -112,7 +111,7 @@
112111
"rimraf": "6.0.1",
113112
"sanitize.css": "^12.0.1",
114113
"semver": "^7.7.1",
115-
"sharp": "^0.34.3",
114+
"sharp": "0.33.3",
116115
"styled-components": "^6.1.15",
117116
"uuid": "11.1.0",
118117
"viem": "^2.26.0",

ts/mains/main_node.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import {
88
app,
99
BrowserWindow,
10+
crashReporter,
1011
protocol as electronProtocol,
1112
ipcMain as ipc,
1213
ipcMain,
@@ -152,6 +153,27 @@ if (!process.mas) {
152153
}
153154
}
154155

156+
/**
157+
* Starts the crash reporter, which saves crashes to disk.
158+
* The dumps will be saved in the `userData/CrashPad/pending` directory.
159+
*
160+
* The minidumps can be read using the `minidump_stackwalk` tool.
161+
* If you do not have cargo installed, you can do those steps:
162+
* ```bash
163+
* git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
164+
* cd depot_tools
165+
* mkdir breakpad && cd breakpad
166+
* ../fetch breakpad && cd src
167+
* ./configure && make
168+
* file src/processor/minidump_stackwalk
169+
* ./src/processor/minidump_stackwalk <path_to.dmp> <any_symbols_you_have_optional>
170+
*/
171+
crashReporter.start({
172+
submitURL: '', // leave empty as we don't want to upload them, but only save them locally
173+
uploadToServer: false,
174+
compress: true,
175+
});
176+
155177
const windowFromUserConfig = userConfig.get('window');
156178
const windowFromEphemeral = ephemeralConfig.get('window');
157179
let windowConfig = windowFromEphemeral || windowFromUserConfig;
@@ -178,6 +200,8 @@ import * as log from '../util/logger/log';
178200
import { DURATION } from '../session/constants';
179201
import { tr } from '../localization/localeTools';
180202

203+
import { logCrash } from '../node/crash/log_crash';
204+
181205
function prepareURL(pathSegments: Array<string>, moreKeys?: { theme: any }) {
182206
const urlObject: url.UrlObject = {
183207
pathname: join(...pathSegments),
@@ -360,6 +384,12 @@ async function createWindow() {
360384
mainWindow.on('focus', setWindowFocus);
361385
mainWindow.on('blur', setWindowFocus);
362386
mainWindow.once('ready-to-show', setWindowFocus);
387+
388+
mainWindow.webContents.on('render-process-gone', (_event, details) => {
389+
// details.reason can be: 'crashed', 'killed', 'oom', etc.
390+
logCrash('renderer', details);
391+
});
392+
363393
// This is a fallback in case we drop an event for some reason.
364394
global.setInterval(setWindowFocus, 5000);
365395

ts/node/crash/log_crash.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { app } from 'electron';
2+
import { appendFileSync } from 'fs-extra';
3+
import path from 'node:path';
4+
5+
/**
6+
* Logs a crash of the renderer/main process to the userData directory, file `crash-log.txt`.
7+
* Also, see the crashReporter for dumps of the crash itself
8+
*/
9+
export function logCrash(type: string, details: any) {
10+
const crashLogPath = path.join(app.getPath('userData'), 'crash-log.txt');
11+
const logLine = `[${new Date().toISOString()}] ${type} crash: ${JSON.stringify(details)}\n`;
12+
appendFileSync(crashLogPath, logLine, 'utf8');
13+
}

ts/node/global_errors.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import os from 'node:os';
33
import { reallyJsonStringify } from '../util/reallyJsonStringify';
44
import { Errors } from '../types/Errors';
55
import { redactAll } from '../util/privacy';
6+
import { logCrash } from './crash/log_crash';
67

78
// TODO: use localised strings
89
const quitText = 'Quit';
@@ -53,10 +54,14 @@ export const addHandler = (): void => {
5354
// Note: we could maybe add a handler for when the renderer process died here?
5455
// (but also ignore the valid death like on restart/quit)
5556
process.on('uncaughtException', (reason: unknown) => {
57+
logCrash('main', { reason: 'uncaughtException', error: reason });
58+
5659
handleError('Unhandled Error', _getError(reason));
5760
});
5861

5962
process.on('unhandledRejection', (reason: unknown) => {
63+
logCrash('main', { reason: 'unhandledRejection', error: reason });
64+
6065
handleError('Unhandled Promise Rejection', _getError(reason));
6166
});
6267
};

ts/webworker/workers/node/image_processor/image_processor.worker.ts

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,12 @@ function centerCoverOpts(maxSidePx: number) {
6363
}
6464

6565
function formattedMetadata(metadata: {
66-
width: number;
67-
height: number;
66+
width: number | undefined;
67+
height: number | undefined;
6868
format: keyof sharp.FormatEnum;
6969
size: number;
7070
}) {
71-
return `(${metadata.width}x${metadata.height} ${metadata.format} of ${metadata.size} bytes)`;
71+
return `(${metadata.width}x${metadata.height}, format:${String(metadata.format)} of ${metadata.size} bytes)`;
7272
}
7373

7474
function sharpFrom(inputBuffer: ArrayBufferLike | Buffer, options?: sharp.SharpOptions) {
@@ -371,7 +371,13 @@ const workerActions: ImageProcessorWorkerActions = {
371371
const start = Date.now();
372372
const metadata = await metadataFromBuffer(inputBuffer);
373373

374-
if (!metadata || !metadata.format || !sharp.format[metadata.format]?.output) {
374+
if (
375+
!metadata ||
376+
!metadata.format ||
377+
!sharp.format[metadata.format]?.output ||
378+
!metadata.width ||
379+
!metadata.height
380+
) {
375381
logIfOn(`Unsupported format: ${metadata?.format}`);
376382
return null;
377383
}
@@ -480,10 +486,10 @@ const workerActions: ImageProcessorWorkerActions = {
480486
}ms for}`
481487
);
482488
logIfOn(
483-
`\t src${formattedMetadata({ width: metadata.width, format: metadata.format, height: metadata.height, size: inputBuffer.byteLength })} `
489+
`\t src${formattedMetadata({ width: metadata.width, height: metadata.height, format: metadata.format, size: inputBuffer.byteLength })} `
484490
);
485491
logIfOn(
486-
`\t dest${formattedMetadata({ width: outputMetadata.width, format: outputMetadata.format, height: outputMetadata.height, size: buffer.buffer.byteLength })} `
492+
`\t dest${formattedMetadata({ width: outputMetadata.width, height: outputMetadata.height, format: metadata.format, size: buffer.buffer.byteLength })} `
487493
);
488494

489495
return {
@@ -501,7 +507,7 @@ const workerActions: ImageProcessorWorkerActions = {
501507
}ms with quality ${quality}`
502508
);
503509
logIfOn(
504-
`\t src${formattedMetadata({ width: metadata.width, format: metadata.format, height: metadata.height, size: inputBuffer.byteLength })} `
510+
`\t src${formattedMetadata({ width: metadata.width, height: metadata.height, format: metadata.format, size: inputBuffer.byteLength })} `
505511
);
506512
}
507513
qualityRangeIndex++;
@@ -513,7 +519,7 @@ const workerActions: ImageProcessorWorkerActions = {
513519
`[imageProcessorWorker] processForFileServerUpload: failed after ${Date.now() - start}ms`
514520
);
515521
logIfOn(
516-
`\t src${formattedMetadata({ width: metadata.width, format: metadata.format, height: metadata.height, size: inputBuffer.byteLength })} `
522+
`\t src${formattedMetadata({ width: metadata.width, height: metadata.height, format: metadata.format, size: inputBuffer.byteLength })} `
517523
);
518524

519525
return null;

0 commit comments

Comments
 (0)