Skip to content

Throw a StateError if ResourceHandle.to* is called more than once. #49878

Closed
@brianquinlan

Description

@brianquinlan

Change

Throw a StateError if ResourceHandle.toFile(), ResourceHandle.toSocket(), ResourceHandle.toRawSocket() or ResourceHandle.toRawDatagramSocket() is called more than once.

Rationale

Calling ResourceHandle.toFile(), ResourceHandle.toSocket(), ResourceHandle.toRawSocket() or ResourceHandle.toRawDatagramSocket() more than once produces two distinct Dart objects that are backed by the same file descriptor, which will become invalid when one object is closed or GCed.

For example:

void main(List<String> args) async {
  final executeInternalCommand = DynamicLibrary.process().lookupFunction<
      Void Function(Pointer<Char>, Pointer<Void>),
      void Function(
          Pointer<Char>, Pointer<Void>)>('Dart_ExecuteInternalCommand');
  final gcNow = "gc-now".toNativeUtf8();

  final file = File('/tmp/file.txt');

  await file.create();
  final openFile = await file.open();

  final handle = ResourceHandle.fromFile(openFile);
  handle.toFile().writeStringSync('test');
  executeInternalCommand(gcNow.cast(), nullptr);  // Will collect the file produced by `toFile` .
  handle.toFile().writeStringSync('test');  // Error because the file descriptor is no longer valid.
}

Impact

It is unlikely that this will break any existing correct code.

Mitigation

Users can save the result of the ResourceHandle.toFile(), etc. and use that instead of calling ResourceHandle.toFile() again.

Metadata

Metadata

Assignees

Labels

area-core-librarySDK core library issues (core, async, ...); use area-vm or area-web for platform specific libraries.breaking-change-requestThis tracks requests for feedback on breaking changeslibrary-io

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions