appium-mac2-driver 3.4.0 → 3.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## [3.4.1](https://github.com/appium/appium-mac2-driver/compare/v3.4.0...v3.4.1) (2026-05-13)
2
+
3
+ ### Bug Fixes
4
+
5
+ * Unhandled error for native video recording ([#383](https://github.com/appium/appium-mac2-driver/issues/383)) ([22a8bff](https://github.com/appium/appium-mac2-driver/commit/22a8bff4efc731b81737fa6d5c36de63582db4f3))
6
+
1
7
  ## [3.4.0](https://github.com/appium/appium-mac2-driver/compare/v3.3.4...v3.4.0) (2026-05-09)
2
8
 
3
9
  ### Features
@@ -13,15 +13,41 @@ interface DisplayInfo {
13
13
  isMain: boolean;
14
14
  }
15
15
  export declare class NativeVideoChunksBroadcaster {
16
- private _ee;
17
- private _log;
18
- private _publishers;
16
+ private readonly _ee;
17
+ private readonly _log;
18
+ private readonly _publishers;
19
+ private readonly _wakeups;
20
+ private readonly _terminationRequests;
19
21
  private _terminated;
20
22
  constructor(ee: EventEmitter, log: AppiumLogger);
21
23
  get hasPublishers(): boolean;
22
24
  schedule(uuid: string): void;
25
+ /**
26
+ * Signals the publisher for `uuid` that its underlying recording has been
27
+ * stopped. The publisher wakes from its current polling sleep, performs a
28
+ * final stat + read + emit pass to flush any remaining bytes of the
29
+ * recording file to BiDi consumers, and exits.
30
+ *
31
+ * Idempotent and safe to call for an unknown uuid (no-op in that case).
32
+ *
33
+ * Callers SHOULD invoke this immediately after the recording has been
34
+ * stopped on the underlying XCTest side; `waitFor(uuid)` is then
35
+ * contractually guaranteed to resolve as soon as the publisher has
36
+ * finished flushing, without having to wait for the next polling tick.
37
+ */
38
+ notifyStopped(uuid: string): void;
23
39
  waitFor(uuid: string): Promise<void>;
24
40
  shutdown(timeoutMs: number): Promise<void>;
41
+ /**
42
+ * Background monitor for a native screen recording attachment.
43
+ *
44
+ * This is scheduled as a fire-and-forget task by {@link schedule} and the
45
+ * resulting promise may sit in `_publishers` for a long time before any
46
+ * consumer awaits it. To make sure a failure here can never surface as an
47
+ * unhandled promise rejection (which terminates the Appium server process
48
+ * on Node.js 24+), this method MUST never reject: every error path logs a
49
+ * warning and returns normally.
50
+ */
25
51
  private _createPublisher;
26
52
  private _wait;
27
53
  private _cleanup;
@@ -1 +1 @@
1
- {"version":3,"file":"native-record-screen.d.ts","sourceRoot":"","sources":["../../../lib/commands/native-record-screen.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,WAAW,CAAC;AAE1C,OAAO,KAAK,EAAC,YAAY,EAAE,YAAY,EAAC,MAAM,eAAe,CAAC;AAC9D,OAAO,KAAK,YAAY,MAAM,aAAa,CAAC;AAY5C,UAAU,eAAe;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,UAAU,WAAW;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,qBAAa,4BAA4B;IACvC,OAAO,CAAC,GAAG,CAAe;IAC1B,OAAO,CAAC,IAAI,CAAe;IAC3B,OAAO,CAAC,WAAW,CAA6B;IAChD,OAAO,CAAC,WAAW,CAAU;gBAEjB,EAAE,EAAE,YAAY,EAAE,GAAG,EAAE,YAAY;IAO/C,IAAI,aAAa,IAAI,OAAO,CAE3B;IAED,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAMtB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOpC,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YAYlC,gBAAgB;YAgEhB,KAAK;YAuBL,QAAQ;CA2BvB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,+BAA+B,CACnD,IAAI,EAAE,UAAU,EAChB,GAAG,CAAC,EAAE,MAAM,EACZ,KAAK,CAAC,EAAE,MAAM,EACd,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,eAAe,CAAC,CAQ1B;AAED;;;;GAIG;AACH,wBAAsB,iCAAiC,CACrD,IAAI,EAAE,UAAU,GACf,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAEjC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAsB,8BAA8B,CAClD,IAAI,EAAE,UAAU,EAChB,UAAU,CAAC,EAAE,MAAM,EACnB,IAAI,CAAC,EAAE,MAAM,EACb,IAAI,CAAC,EAAE,MAAM,EACb,MAAM,CAAC,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,YAAY,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,EACxC,aAAa,CAAC,EAAE,MAAM,EACtB,UAAU,CAAC,EAAE,YAAY,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,EAC9C,aAAa,CAAC,EAAE,OAAO,GACtB,OAAO,CAAC,MAAM,CAAC,CAkDjB;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC,CAE5F"}
1
+ {"version":3,"file":"native-record-screen.d.ts","sourceRoot":"","sources":["../../../lib/commands/native-record-screen.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,WAAW,CAAC;AAE1C,OAAO,KAAK,EAAC,YAAY,EAAE,YAAY,EAAC,MAAM,eAAe,CAAC;AAC9D,OAAO,KAAK,YAAY,MAAM,aAAa,CAAC;AAc5C,UAAU,eAAe;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,UAAU,WAAW;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,qBAAa,4BAA4B;IACvC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;IACnC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAe;IACpC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA6B;IAIzD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAwC;IAKjE,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAc;IACnD,OAAO,CAAC,WAAW,CAAU;gBAEjB,EAAE,EAAE,YAAY,EAAE,GAAG,EAAE,YAAY;IAS/C,IAAI,aAAa,IAAI,OAAO,CAE3B;IAED,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAM5B;;;;;;;;;;;;OAYG;IACH,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAQ3B,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOpC,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAmBhD;;;;;;;;;OASG;YACW,gBAAgB;YA+GhB,KAAK;YAiBL,QAAQ;CA2BvB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,+BAA+B,CACnD,IAAI,EAAE,UAAU,EAChB,GAAG,CAAC,EAAE,MAAM,EACZ,KAAK,CAAC,EAAE,MAAM,EACd,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,eAAe,CAAC,CAQ1B;AAED;;;;GAIG;AACH,wBAAsB,iCAAiC,CACrD,IAAI,EAAE,UAAU,GACf,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAEjC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAsB,8BAA8B,CAClD,IAAI,EAAE,UAAU,EAChB,UAAU,CAAC,EAAE,MAAM,EACnB,IAAI,CAAC,EAAE,MAAM,EACb,IAAI,CAAC,EAAE,MAAM,EACb,MAAM,CAAC,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,YAAY,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,EACxC,aAAa,CAAC,EAAE,MAAM,EACtB,UAAU,CAAC,EAAE,YAAY,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,EAC9C,aAAa,CAAC,EAAE,OAAO,GACtB,OAAO,CAAC,MAAM,CAAC,CAuDjB;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC,CAE5F"}
@@ -8,7 +8,6 @@ exports.macosStartNativeScreenRecording = macosStartNativeScreenRecording;
8
8
  exports.macosGetNativeScreenRecordingInfo = macosGetNativeScreenRecordingInfo;
9
9
  exports.macosStopNativeScreenRecording = macosStopNativeScreenRecording;
10
10
  exports.macosListDisplays = macosListDisplays;
11
- const promises_1 = require("node:timers/promises");
12
11
  const node_path_1 = __importDefault(require("node:path"));
13
12
  const support_1 = require("appium/support");
14
13
  const helpers_1 = require("./helpers");
@@ -21,15 +20,27 @@ const RECORDING_STARTUP_TIMEOUT_MS = 5000;
21
20
  const BUFFER_SIZE = 0xffff;
22
21
  const MONITORING_INTERVAL_DURATION_MS = 1000;
23
22
  const MAX_MONITORING_DURATION_MS = 24 * 60 * 60 * 1000; // 1 day
23
+ const STOP_WAIT_TIMEOUT_MS = 5000;
24
24
  class NativeVideoChunksBroadcaster {
25
25
  _ee;
26
26
  _log;
27
27
  _publishers;
28
+ // The currently scheduled polling sleep of each publisher, indexed by uuid.
29
+ // Cancelling it wakes the publisher up before the next polling tick so it
30
+ // can perform a final stat + read + emit pass and exit.
31
+ _wakeups;
32
+ // Set of uuids whose underlying recording has been explicitly stopped via
33
+ // `notifyStopped`. The publisher uses this as the primary completion
34
+ // signal; the `lsof` check is only consulted as a fallback for the case
35
+ // where the host XCTest process disappears without anyone telling us.
36
+ _terminationRequests;
28
37
  _terminated;
29
38
  constructor(ee, log) {
30
39
  this._ee = ee;
31
40
  this._log = log;
32
41
  this._publishers = new Map();
42
+ this._wakeups = new Map();
43
+ this._terminationRequests = new Set();
33
44
  this._terminated = false;
34
45
  }
35
46
  get hasPublishers() {
@@ -40,6 +51,26 @@ class NativeVideoChunksBroadcaster {
40
51
  this._publishers.set(uuid, this._createPublisher(uuid));
41
52
  }
42
53
  }
54
+ /**
55
+ * Signals the publisher for `uuid` that its underlying recording has been
56
+ * stopped. The publisher wakes from its current polling sleep, performs a
57
+ * final stat + read + emit pass to flush any remaining bytes of the
58
+ * recording file to BiDi consumers, and exits.
59
+ *
60
+ * Idempotent and safe to call for an unknown uuid (no-op in that case).
61
+ *
62
+ * Callers SHOULD invoke this immediately after the recording has been
63
+ * stopped on the underlying XCTest side; `waitFor(uuid)` is then
64
+ * contractually guaranteed to resolve as soon as the publisher has
65
+ * finished flushing, without having to wait for the next polling tick.
66
+ */
67
+ notifyStopped(uuid) {
68
+ if (!this._publishers.has(uuid)) {
69
+ return;
70
+ }
71
+ this._terminationRequests.add(uuid);
72
+ this._wakeups.get(uuid)?.cancel();
73
+ }
43
74
  async waitFor(uuid) {
44
75
  const publisher = this._publishers.get(uuid);
45
76
  if (publisher) {
@@ -47,6 +78,11 @@ class NativeVideoChunksBroadcaster {
47
78
  }
48
79
  }
49
80
  async shutdown(timeoutMs) {
81
+ // Wake up every active publisher so they don't have to wait for their
82
+ // next polling tick before flushing and exiting.
83
+ for (const uuid of this._publishers.keys()) {
84
+ this.notifyStopped(uuid);
85
+ }
50
86
  try {
51
87
  await this._wait(timeoutMs);
52
88
  }
@@ -54,11 +90,22 @@ class NativeVideoChunksBroadcaster {
54
90
  this._log.warn(e instanceof Error ? e.message : String(e));
55
91
  }
56
92
  await this._cleanup();
57
- this._publishers = new Map();
93
+ this._publishers.clear();
94
+ this._wakeups.clear();
95
+ this._terminationRequests.clear();
58
96
  }
97
+ /**
98
+ * Background monitor for a native screen recording attachment.
99
+ *
100
+ * This is scheduled as a fire-and-forget task by {@link schedule} and the
101
+ * resulting promise may sit in `_publishers` for a long time before any
102
+ * consumer awaits it. To make sure a failure here can never surface as an
103
+ * unhandled promise rejection (which terminates the Appium server process
104
+ * on Node.js 24+), this method MUST never reject: every error path logs a
105
+ * warning and returns normally.
106
+ */
59
107
  async _createPublisher(uuid) {
60
108
  let fullPath = '';
61
- let bytesRead = 0n;
62
109
  try {
63
110
  await (0, asyncbox_1.waitForCondition)(async () => {
64
111
  const paths = await listAttachments();
@@ -74,33 +121,81 @@ class NativeVideoChunksBroadcaster {
74
121
  });
75
122
  }
76
123
  catch {
77
- throw new Error(`The video recording identified by ${uuid} did not ` +
124
+ this._log.warn(`The video recording identified by ${uuid} did not ` +
78
125
  `start within ${RECORDING_STARTUP_TIMEOUT_MS}ms timeout`);
126
+ return;
79
127
  }
128
+ let bytesRead = 0n;
80
129
  const startedMs = performance.now();
81
- while (!this._terminated && performance.now() - startedMs < MAX_MONITORING_DURATION_MS) {
82
- const isCompleted = !(await isFileUsed(fullPath, 'testman'));
83
- const { size } = await support_1.fs.stat(fullPath, { bigint: true });
84
- if (bytesRead < size) {
85
- const handle = await support_1.fs.open(fullPath, 'r');
130
+ try {
131
+ while (!this._terminated && performance.now() - startedMs < MAX_MONITORING_DURATION_MS) {
132
+ // Primary completion signal: `notifyStopped(uuid)` was called.
133
+ // Secondary fallback: lsof reports no `testman` process holding
134
+ // the recording file open (e.g. the host process exited without
135
+ // anyone telling us — see appium/appium#22269).
136
+ const stopRequested = this._terminationRequests.has(uuid);
137
+ const isCompleted = stopRequested || !(await isFileUsed(fullPath, 'testman'));
138
+ let size;
86
139
  try {
87
- while (bytesRead < size) {
88
- const bufferSize = Number(size - bytesRead > BUFFER_SIZE ? BUFFER_SIZE : size - bytesRead);
89
- const buf = Buffer.alloc(bufferSize);
90
- await support_1.fs.read(handle, buf, 0, bufferSize, bytesRead);
91
- this._ee.emit(constants_1.BIDI_EVENT_NAME, (0, models_1.toNativeVideoChunkAddedEvent)(uuid, buf));
92
- bytesRead += BigInt(bufferSize);
140
+ ({ size } = await support_1.fs.stat(fullPath, { bigint: true }));
141
+ }
142
+ catch (e) {
143
+ // The recording file may have been removed by the OS once the
144
+ // host XCTest process owning the attachment has exited. In that
145
+ // case there is nothing more to read and we should stop monitoring.
146
+ if (e?.code === 'ENOENT') {
147
+ this._log.debug(`The native video recording file for ${uuid} is no longer available. ` +
148
+ `Assuming the recording has been terminated`);
149
+ return;
93
150
  }
151
+ throw e;
152
+ }
153
+ if (bytesRead < size) {
154
+ const handle = await support_1.fs.open(fullPath, 'r');
155
+ try {
156
+ while (bytesRead < size) {
157
+ const bufferSize = Number(size - bytesRead > BUFFER_SIZE ? BUFFER_SIZE : size - bytesRead);
158
+ const buf = Buffer.alloc(bufferSize);
159
+ await support_1.fs.read(handle, buf, 0, bufferSize, bytesRead);
160
+ this._ee.emit(constants_1.BIDI_EVENT_NAME, (0, models_1.toNativeVideoChunkAddedEvent)(uuid, buf));
161
+ bytesRead += BigInt(bufferSize);
162
+ }
163
+ }
164
+ finally {
165
+ await support_1.fs.close(handle);
166
+ }
167
+ }
168
+ if (isCompleted) {
169
+ this._log.debug(`The native video recording identified by ${uuid} has been detected as completed`);
170
+ return;
171
+ }
172
+ // Cancellable sleep until the next polling tick. `notifyStopped`
173
+ // cancels this wakeup so the loop re-runs immediately and detects
174
+ // termination on the very next iteration. `cancelError: null` makes
175
+ // the cancel resolve the promise instead of rejecting it.
176
+ const wakeup = (0, asyncbox_1.sleep)({ ms: MONITORING_INTERVAL_DURATION_MS, cancelError: null });
177
+ this._wakeups.set(uuid, wakeup);
178
+ try {
179
+ // Guard against a notifyStopped() that landed between the
180
+ // iteration's stop-check above and the wakeup being stored:
181
+ // the cancel above would have been a no-op, so cancel here.
182
+ if (this._terminationRequests.has(uuid)) {
183
+ wakeup.cancel();
184
+ }
185
+ await wakeup;
94
186
  }
95
187
  finally {
96
- await support_1.fs.close(handle);
188
+ this._wakeups.delete(uuid);
97
189
  }
98
190
  }
99
- if (isCompleted) {
100
- this._log.debug(`The native video recording identified by ${uuid} has been detected as completed`);
101
- return;
102
- }
103
- await (0, promises_1.setTimeout)(MONITORING_INTERVAL_DURATION_MS);
191
+ }
192
+ catch (e) {
193
+ this._log.warn(`Native video chunks publisher for ${uuid} stopped unexpectedly: ` +
194
+ (e instanceof Error ? e.message : String(e)));
195
+ return;
196
+ }
197
+ finally {
198
+ this._terminationRequests.delete(uuid);
104
199
  }
105
200
  this._log.warn(`Stopped monitoring of the native video recording identified by ${uuid} ` +
106
201
  `because of the timeout`);
@@ -112,18 +207,13 @@ class NativeVideoChunksBroadcaster {
112
207
  const timer = setTimeout(() => {
113
208
  this._terminated = true;
114
209
  }, timeoutMs);
115
- const publishingErrors = [];
116
- for (const publisher of this._publishers.values()) {
117
- try {
118
- await publisher;
119
- }
120
- catch (e) {
121
- publishingErrors.push(e instanceof Error ? e.message : String(e));
122
- }
210
+ try {
211
+ // Publishers are guaranteed by `_createPublisher` to never reject,
212
+ // so we can simply await all of them.
213
+ await Promise.all(this._publishers.values());
123
214
  }
124
- clearTimeout(timer);
125
- if (publishingErrors.length > 0) {
126
- throw new Error(publishingErrors.join('\n'));
215
+ finally {
216
+ clearTimeout(timer);
127
217
  }
128
218
  }
129
219
  async _cleanup() {
@@ -216,13 +306,18 @@ async function macosStopNativeScreenRecording(remotePath, user, pass, method, he
216
306
  throw new Error('There is no active screen recording, thus nothing to stop. Did you start it before?');
217
307
  }
218
308
  const { uuid } = response;
309
+ // Wake the publisher up so it stops polling and flushes any remaining
310
+ // bytes immediately. Without this, `waitFor` below could still block
311
+ // for up to `MONITORING_INTERVAL_DURATION_MS` while the publisher sits
312
+ // in its polling sleep.
313
+ this._videoChunksBroadcaster.notifyStopped(uuid);
219
314
  try {
220
- await (0, asyncbox_1.withTimeout)(this._videoChunksBroadcaster.waitFor(uuid), 5000);
315
+ await (0, asyncbox_1.withTimeout)(this._videoChunksBroadcaster.waitFor(uuid), STOP_WAIT_TIMEOUT_MS);
221
316
  }
222
317
  catch (e) {
223
318
  if (e instanceof asyncbox_1.TimeoutError) {
224
319
  this.log.debug(`The BiDi chunks broadcaster for the native screen recording identified ` +
225
- `by ${uuid} cannot complete within 5000ms timeout`);
320
+ `by ${uuid} cannot complete within ${STOP_WAIT_TIMEOUT_MS}ms timeout`);
226
321
  }
227
322
  else {
228
323
  this.log.debug(e instanceof Error ? e.stack : String(e));
@@ -268,7 +363,12 @@ async function listAttachments() {
268
363
  });
269
364
  }
270
365
  async function isFileUsed(fpath, userProcessName) {
271
- const { stdout } = await (0, teen_process_1.exec)('lsof', [fpath]);
272
- return stdout.includes(userProcessName);
366
+ try {
367
+ const { stdout } = await (0, teen_process_1.exec)('lsof', [fpath]);
368
+ return stdout.includes(userProcessName);
369
+ }
370
+ catch {
371
+ return false;
372
+ }
273
373
  }
274
374
  //# sourceMappingURL=native-record-screen.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"native-record-screen.js","sourceRoot":"","sources":["../../../lib/commands/native-record-screen.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"native-record-screen.js","sourceRoot":"","sources":["../../../lib/commands/native-record-screen.ts"],"names":[],"mappings":"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"}
@@ -1,11 +1,11 @@
1
- import {setTimeout as delay} from 'node:timers/promises';
2
1
  import path from 'node:path';
3
2
  import {fs, util} from 'appium/support';
4
3
  import type {Mac2Driver} from '../driver';
5
4
  import {uploadRecordedMedia} from './helpers';
6
5
  import type {AppiumLogger, StringRecord} from '@appium/types';
7
6
  import type EventEmitter from 'node:events';
8
- import {TimeoutError, waitForCondition, withTimeout} from 'asyncbox';
7
+ import type {CancellablePromise} from 'asyncbox';
8
+ import {TimeoutError, sleep, waitForCondition, withTimeout} from 'asyncbox';
9
9
  import {exec} from 'teen_process';
10
10
  import {BIDI_EVENT_NAME} from './bidi/constants';
11
11
  import {toNativeVideoChunkAddedEvent} from './bidi/models';
@@ -15,6 +15,7 @@ const RECORDING_STARTUP_TIMEOUT_MS = 5000;
15
15
  const BUFFER_SIZE = 0xffff;
16
16
  const MONITORING_INTERVAL_DURATION_MS = 1000;
17
17
  const MAX_MONITORING_DURATION_MS = 24 * 60 * 60 * 1000; // 1 day
18
+ const STOP_WAIT_TIMEOUT_MS = 5000;
18
19
 
19
20
  interface ActiveVideoInfo {
20
21
  fps: number;
@@ -30,15 +31,26 @@ interface DisplayInfo {
30
31
  }
31
32
 
32
33
  export class NativeVideoChunksBroadcaster {
33
- private _ee: EventEmitter;
34
- private _log: AppiumLogger;
35
- private _publishers: Map<string, Promise<void>>;
34
+ private readonly _ee: EventEmitter;
35
+ private readonly _log: AppiumLogger;
36
+ private readonly _publishers: Map<string, Promise<void>>;
37
+ // The currently scheduled polling sleep of each publisher, indexed by uuid.
38
+ // Cancelling it wakes the publisher up before the next polling tick so it
39
+ // can perform a final stat + read + emit pass and exit.
40
+ private readonly _wakeups: Map<string, CancellablePromise<void>>;
41
+ // Set of uuids whose underlying recording has been explicitly stopped via
42
+ // `notifyStopped`. The publisher uses this as the primary completion
43
+ // signal; the `lsof` check is only consulted as a fallback for the case
44
+ // where the host XCTest process disappears without anyone telling us.
45
+ private readonly _terminationRequests: Set<string>;
36
46
  private _terminated: boolean;
37
47
 
38
48
  constructor(ee: EventEmitter, log: AppiumLogger) {
39
49
  this._ee = ee;
40
50
  this._log = log;
41
51
  this._publishers = new Map();
52
+ this._wakeups = new Map();
53
+ this._terminationRequests = new Set();
42
54
  this._terminated = false;
43
55
  }
44
56
 
@@ -52,6 +64,27 @@ export class NativeVideoChunksBroadcaster {
52
64
  }
53
65
  }
54
66
 
67
+ /**
68
+ * Signals the publisher for `uuid` that its underlying recording has been
69
+ * stopped. The publisher wakes from its current polling sleep, performs a
70
+ * final stat + read + emit pass to flush any remaining bytes of the
71
+ * recording file to BiDi consumers, and exits.
72
+ *
73
+ * Idempotent and safe to call for an unknown uuid (no-op in that case).
74
+ *
75
+ * Callers SHOULD invoke this immediately after the recording has been
76
+ * stopped on the underlying XCTest side; `waitFor(uuid)` is then
77
+ * contractually guaranteed to resolve as soon as the publisher has
78
+ * finished flushing, without having to wait for the next polling tick.
79
+ */
80
+ notifyStopped(uuid: string): void {
81
+ if (!this._publishers.has(uuid)) {
82
+ return;
83
+ }
84
+ this._terminationRequests.add(uuid);
85
+ this._wakeups.get(uuid)?.cancel();
86
+ }
87
+
55
88
  async waitFor(uuid: string): Promise<void> {
56
89
  const publisher = this._publishers.get(uuid);
57
90
  if (publisher) {
@@ -60,6 +93,11 @@ export class NativeVideoChunksBroadcaster {
60
93
  }
61
94
 
62
95
  async shutdown(timeoutMs: number): Promise<void> {
96
+ // Wake up every active publisher so they don't have to wait for their
97
+ // next polling tick before flushing and exiting.
98
+ for (const uuid of this._publishers.keys()) {
99
+ this.notifyStopped(uuid);
100
+ }
63
101
  try {
64
102
  await this._wait(timeoutMs);
65
103
  } catch (e) {
@@ -68,12 +106,23 @@ export class NativeVideoChunksBroadcaster {
68
106
 
69
107
  await this._cleanup();
70
108
 
71
- this._publishers = new Map();
109
+ this._publishers.clear();
110
+ this._wakeups.clear();
111
+ this._terminationRequests.clear();
72
112
  }
73
113
 
114
+ /**
115
+ * Background monitor for a native screen recording attachment.
116
+ *
117
+ * This is scheduled as a fire-and-forget task by {@link schedule} and the
118
+ * resulting promise may sit in `_publishers` for a long time before any
119
+ * consumer awaits it. To make sure a failure here can never surface as an
120
+ * unhandled promise rejection (which terminates the Appium server process
121
+ * on Node.js 24+), this method MUST never reject: every error path logs a
122
+ * warning and returns normally.
123
+ */
74
124
  private async _createPublisher(uuid: string): Promise<void> {
75
125
  let fullPath = '';
76
- let bytesRead = 0n;
77
126
  try {
78
127
  await waitForCondition(
79
128
  async () => {
@@ -91,42 +140,90 @@ export class NativeVideoChunksBroadcaster {
91
140
  },
92
141
  );
93
142
  } catch {
94
- throw new Error(
143
+ this._log.warn(
95
144
  `The video recording identified by ${uuid} did not ` +
96
145
  `start within ${RECORDING_STARTUP_TIMEOUT_MS}ms timeout`,
97
146
  );
147
+ return;
98
148
  }
99
149
 
150
+ let bytesRead = 0n;
100
151
  const startedMs = performance.now();
101
- while (!this._terminated && performance.now() - startedMs < MAX_MONITORING_DURATION_MS) {
102
- const isCompleted = !(await isFileUsed(fullPath, 'testman'));
152
+ try {
153
+ while (!this._terminated && performance.now() - startedMs < MAX_MONITORING_DURATION_MS) {
154
+ // Primary completion signal: `notifyStopped(uuid)` was called.
155
+ // Secondary fallback: lsof reports no `testman` process holding
156
+ // the recording file open (e.g. the host process exited without
157
+ // anyone telling us — see appium/appium#22269).
158
+ const stopRequested = this._terminationRequests.has(uuid);
159
+ const isCompleted = stopRequested || !(await isFileUsed(fullPath, 'testman'));
103
160
 
104
- const {size} = await fs.stat(fullPath, {bigint: true});
105
- if (bytesRead < size) {
106
- const handle = await fs.open(fullPath, 'r');
161
+ let size: bigint;
107
162
  try {
108
- while (bytesRead < size) {
109
- const bufferSize = Number(
110
- size - bytesRead > BUFFER_SIZE ? BUFFER_SIZE : size - bytesRead,
163
+ ({size} = await fs.stat(fullPath, {bigint: true}));
164
+ } catch (e) {
165
+ // The recording file may have been removed by the OS once the
166
+ // host XCTest process owning the attachment has exited. In that
167
+ // case there is nothing more to read and we should stop monitoring.
168
+ if ((e as NodeJS.ErrnoException)?.code === 'ENOENT') {
169
+ this._log.debug(
170
+ `The native video recording file for ${uuid} is no longer available. ` +
171
+ `Assuming the recording has been terminated`,
111
172
  );
112
- const buf = Buffer.alloc(bufferSize);
113
- await fs.read(handle, buf as any, 0, bufferSize, bytesRead as any);
114
- this._ee.emit(BIDI_EVENT_NAME, toNativeVideoChunkAddedEvent(uuid, buf));
115
- bytesRead += BigInt(bufferSize);
173
+ return;
174
+ }
175
+ throw e;
176
+ }
177
+ if (bytesRead < size) {
178
+ const handle = await fs.open(fullPath, 'r');
179
+ try {
180
+ while (bytesRead < size) {
181
+ const bufferSize = Number(
182
+ size - bytesRead > BUFFER_SIZE ? BUFFER_SIZE : size - bytesRead,
183
+ );
184
+ const buf = Buffer.alloc(bufferSize);
185
+ await fs.read(handle, buf as any, 0, bufferSize, bytesRead as any);
186
+ this._ee.emit(BIDI_EVENT_NAME, toNativeVideoChunkAddedEvent(uuid, buf));
187
+ bytesRead += BigInt(bufferSize);
188
+ }
189
+ } finally {
190
+ await fs.close(handle);
116
191
  }
117
- } finally {
118
- await fs.close(handle);
119
192
  }
120
- }
121
193
 
122
- if (isCompleted) {
123
- this._log.debug(
124
- `The native video recording identified by ${uuid} has been detected as completed`,
125
- );
126
- return;
127
- }
194
+ if (isCompleted) {
195
+ this._log.debug(
196
+ `The native video recording identified by ${uuid} has been detected as completed`,
197
+ );
198
+ return;
199
+ }
128
200
 
129
- await delay(MONITORING_INTERVAL_DURATION_MS);
201
+ // Cancellable sleep until the next polling tick. `notifyStopped`
202
+ // cancels this wakeup so the loop re-runs immediately and detects
203
+ // termination on the very next iteration. `cancelError: null` makes
204
+ // the cancel resolve the promise instead of rejecting it.
205
+ const wakeup = sleep({ms: MONITORING_INTERVAL_DURATION_MS, cancelError: null});
206
+ this._wakeups.set(uuid, wakeup);
207
+ try {
208
+ // Guard against a notifyStopped() that landed between the
209
+ // iteration's stop-check above and the wakeup being stored:
210
+ // the cancel above would have been a no-op, so cancel here.
211
+ if (this._terminationRequests.has(uuid)) {
212
+ wakeup.cancel();
213
+ }
214
+ await wakeup;
215
+ } finally {
216
+ this._wakeups.delete(uuid);
217
+ }
218
+ }
219
+ } catch (e) {
220
+ this._log.warn(
221
+ `Native video chunks publisher for ${uuid} stopped unexpectedly: ` +
222
+ (e instanceof Error ? e.message : String(e)),
223
+ );
224
+ return;
225
+ } finally {
226
+ this._terminationRequests.delete(uuid);
130
227
  }
131
228
 
132
229
  this._log.warn(
@@ -143,18 +240,12 @@ export class NativeVideoChunksBroadcaster {
143
240
  const timer = setTimeout(() => {
144
241
  this._terminated = true;
145
242
  }, timeoutMs);
146
- const publishingErrors: string[] = [];
147
- for (const publisher of this._publishers.values()) {
148
- try {
149
- await publisher;
150
- } catch (e) {
151
- publishingErrors.push(e instanceof Error ? e.message : String(e));
152
- }
153
- }
154
- clearTimeout(timer);
155
-
156
- if (publishingErrors.length > 0) {
157
- throw new Error(publishingErrors.join('\n'));
243
+ try {
244
+ // Publishers are guaranteed by `_createPublisher` to never reject,
245
+ // so we can simply await all of them.
246
+ await Promise.all(this._publishers.values());
247
+ } finally {
248
+ clearTimeout(timer);
158
249
  }
159
250
  }
160
251
 
@@ -278,13 +369,18 @@ export async function macosStopNativeScreenRecording(
278
369
  }
279
370
 
280
371
  const {uuid} = response;
372
+ // Wake the publisher up so it stops polling and flushes any remaining
373
+ // bytes immediately. Without this, `waitFor` below could still block
374
+ // for up to `MONITORING_INTERVAL_DURATION_MS` while the publisher sits
375
+ // in its polling sleep.
376
+ this._videoChunksBroadcaster.notifyStopped(uuid);
281
377
  try {
282
- await withTimeout(this._videoChunksBroadcaster.waitFor(uuid), 5000);
378
+ await withTimeout(this._videoChunksBroadcaster.waitFor(uuid), STOP_WAIT_TIMEOUT_MS);
283
379
  } catch (e) {
284
380
  if (e instanceof TimeoutError) {
285
381
  this.log.debug(
286
382
  `The BiDi chunks broadcaster for the native screen recording identified ` +
287
- `by ${uuid} cannot complete within 5000ms timeout`,
383
+ `by ${uuid} cannot complete within ${STOP_WAIT_TIMEOUT_MS}ms timeout`,
288
384
  );
289
385
  } else {
290
386
  this.log.debug(e instanceof Error ? e.stack : String(e));
@@ -341,6 +437,10 @@ async function listAttachments(): Promise<string[]> {
341
437
  }
342
438
 
343
439
  async function isFileUsed(fpath: string, userProcessName: string): Promise<boolean> {
344
- const {stdout} = await exec('lsof', [fpath]);
345
- return stdout.includes(userProcessName);
440
+ try {
441
+ const {stdout} = await exec('lsof', [fpath]);
442
+ return stdout.includes(userProcessName);
443
+ } catch {
444
+ return false;
445
+ }
346
446
  }
@@ -1,20 +1,20 @@
1
1
  {
2
2
  "name": "appium-mac2-driver",
3
- "version": "3.4.0",
3
+ "version": "3.4.1",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "appium-mac2-driver",
9
- "version": "3.4.0",
9
+ "version": "3.4.1",
10
10
  "license": "Apache-2.0",
11
11
  "dependencies": {
12
12
  "@appium/strongbox": "^1.0.0-rc.1",
13
13
  "@colors/colors": "^1.6.0",
14
14
  "appium-xcode": "^6.0.0",
15
- "asyncbox": "^6.0.1",
16
- "axios": "^1.x",
17
- "portscanner": "2.2.0",
15
+ "asyncbox": "^6.3.0",
16
+ "axios": "^1.16.0",
17
+ "portscanner": "^2.2.0",
18
18
  "teen_process": "^4.0.4"
19
19
  },
20
20
  "devDependencies": {
@@ -138,6 +138,19 @@
138
138
  "sharp": "0.34.5"
139
139
  }
140
140
  },
141
+ "node_modules/@appium/support/node_modules/asyncbox": {
142
+ "version": "6.2.0",
143
+ "resolved": "https://registry.npmjs.org/asyncbox/-/asyncbox-6.2.0.tgz",
144
+ "integrity": "sha512-z1XpHkoT3y+1aXfazEY5d7HN2eOi50fLq7ZTxG0H4WegLxrtEAI5Vsc6OR9dOwoC3SJQLXyV0ZVnPEh6GIgMKQ==",
145
+ "license": "Apache-2.0",
146
+ "dependencies": {
147
+ "p-limit": "^7.2.0"
148
+ },
149
+ "engines": {
150
+ "node": "^20.19.0 || ^22.12.0 || >=24.0.0",
151
+ "npm": ">=10"
152
+ }
153
+ },
141
154
  "node_modules/@appium/tsconfig": {
142
155
  "version": "1.1.2",
143
156
  "resolved": "https://registry.npmjs.org/@appium/tsconfig/-/tsconfig-1.1.2.tgz",
@@ -556,9 +569,9 @@
556
569
  "license": "MIT"
557
570
  },
558
571
  "node_modules/asyncbox": {
559
- "version": "6.2.0",
560
- "resolved": "https://registry.npmjs.org/asyncbox/-/asyncbox-6.2.0.tgz",
561
- "integrity": "sha512-z1XpHkoT3y+1aXfazEY5d7HN2eOi50fLq7ZTxG0H4WegLxrtEAI5Vsc6OR9dOwoC3SJQLXyV0ZVnPEh6GIgMKQ==",
572
+ "version": "6.3.0",
573
+ "resolved": "https://registry.npmjs.org/asyncbox/-/asyncbox-6.3.0.tgz",
574
+ "integrity": "sha512-7IFpnQDltd5rYQjhIJIpyismJtdWmw/pOABZKJfv2WVo0a6iYh2ZzUuCJJclae5mBtK0H/EychxXg91GB7rGdQ==",
562
575
  "license": "Apache-2.0",
563
576
  "dependencies": {
564
577
  "p-limit": "^7.2.0"
package/package.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "mac",
7
7
  "XCTest"
8
8
  ],
9
- "version": "3.4.0",
9
+ "version": "3.4.1",
10
10
  "author": "Appium Contributors",
11
11
  "license": "Apache-2.0",
12
12
  "repository": {
@@ -49,9 +49,9 @@
49
49
  "@appium/strongbox": "^1.0.0-rc.1",
50
50
  "@colors/colors": "^1.6.0",
51
51
  "appium-xcode": "^6.0.0",
52
- "asyncbox": "^6.0.1",
53
- "axios": "^1.x",
54
- "portscanner": "2.2.0",
52
+ "asyncbox": "^6.3.0",
53
+ "axios": "^1.16.0",
54
+ "portscanner": "^2.2.0",
55
55
  "teen_process": "^4.0.4"
56
56
  },
57
57
  "scripts": {