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

[breaking change] Remove dart:cli waitFor experiment #52121

Closed
mraleph opened this issue Apr 21, 2023 · 45 comments
Closed

[breaking change] Remove dart:cli waitFor experiment #52121

mraleph opened this issue Apr 21, 2023 · 45 comments
Assignees
Labels
area-library breaking-change-approved breaking-change-request This tracks requests for feedback on breaking changes

Comments

@mraleph
Copy link
Member

mraleph commented Apr 21, 2023

Change Intent

waitFor contradicts Dart's event-loop model in a way that no other old or new feature does: it allows async and synchronous code to interleave. The feature has been marked experimental since the beginning and effectively has only two users: sass and dcli package. It is not available in Flutter or on the Web because dart:cli library is not exposed there.

See discussion on #39390 for context.

Justification

We would like to reduce VM's technical debt by removing this experimental functionality, which we believe was added hastily and without due thought to the consequences.

We also have some indications (based on some internal code which has been migrated from waitFor) that availability of waitFor encourages ineffecient and convoluted coding patterns.

If you compare waitFor with Finalizer (which was added in 2.17) you will observe that we choose to make Finalizer less powerful by specifying that finalizers are only invoked at the turn of the event loop for the sake of maintaining semantic purity around interleaving of synchronous code.

Impact

Current users (which basically amounts to dcli and sass) will have to migrate off waitFor which will require them to rewrite their code.

Mitigation

Based on our analysis of dcli and sass multiple migration strategies are available:

  • The usage of asynchronous dart:io methods can be replaced with synchronous counterparts, eliminating the need for waitFor;
  • Asynchronous code can be moved to a helper isolate which communicates with the main isolate through synchronous communication channel built on top of low-level dart:ffi primitives;
  • Synchronous code be rewritten to become asynchronous, following Dart's canonical style for writing such code.

Note that it is an explicit non-goal to provide a completely equivalent replacement for waitFor, because we believe the feature itself is incompatible with how Dart's async is designed and should be removed.

Synchronous communication over dart:ffi

This code demonstrates how dart:ffi can be used to establish an entirely synchronous communication channel between the main (dispatcher) isolate and a worker isolate. This type of communication channel should cover sass needs.

To make migration simpler we will provide a portable synchronization package which implements mutexes and conditional variables, though we leave implementation of cross-isolate communication channels to the developers.

Isolate.resolvePackageUri

Some minor users of waitFor use it to synchronously unwrap Future returned from Isolate.resolvePackageUri API. In reality the underlying implementation of Isolate.resolvePackageUri is entirely synchronous.

While there is migration path for this code using dart:ffi and isolates we can simplify things by directly exposing Isolate.resolvePackageUriSync(...) and deprecating async version of this API.

Timeline

The removal will follow this timeline:

  • Dart 2.15: The waitForfeature was marked deprecated
  • Dart 3.0: We announce the upcoming removal, offering ~1 year migration timeline
  • Dart 3.3: waitFor is now disabled by default, but can be temporarily enabled by passing the flag --enable_deprecated_wait_for to the VM / dart command
  • Dart 3.4: We'll fully remove waitFor and there will be no way of enabling it
@mraleph mraleph added the breaking-change-request This tracks requests for feedback on breaking changes label Apr 21, 2023
@mraleph
Copy link
Member Author

mraleph commented Apr 21, 2023

/cc @mit-mit @lrhn @mkustermann @vsmenon

@itsjustkevin
Copy link
Contributor

@grouma does this affect your teams?
@Hixie this mentions that it does not touch flutter.

@mraleph if we are targeting 3.2 this would most likely give users around 6 months to migrate.

@lrhn
Copy link
Member

lrhn commented Apr 21, 2023

I think it's a good idea that the Dart team provides the the low-level mutex and message-passing package, implemented using dart:ffi. Probably as a tools package.
That makes it possible for us to change the implementation in the future, if we, for example, stop using pthreads in the stand-alone VM.

I'd rather not have user-written Dart code depend on pthreads being available in the dart process.
In fact, we should probably say somewhere that we do not guarantee such things.

We should make sure the package is designed abstractly enough, so we don't bind ourselves to a particular mutex implementation. (And we should document that in the package, so future maintainers won't start providing more implementation specific primitives.)

LGTM.

@mraleph
Copy link
Member Author

mraleph commented Apr 21, 2023

@mraleph if we are targeting 3.2 this would most likely give users around 6 months to migrate.

I was somehow thinking that we only do stable release every 6 months, but it seems that target cadence is quarterly. I am happy to commit to removing it in 3.4 instead of 3.2 to give full year. Updated the issue text to reflect this timeline.

@grouma
Copy link
Member

grouma commented Apr 21, 2023

@grouma does this affect your teams?

Implicitly through sass but not directly. The sass impact is constrained to a single file.

@timsneath
Copy link
Contributor

timsneath commented Apr 21, 2023

This seems like a good path forward. Thanks, @mraleph.

To simplify downstream compatibility, it would be helpful to have at least one release where both waitFor and the new sync APIs (such as resolvePackageUriSync) are available. That is, if we introduce resolvePackageUriSync in 3.1, we shouldn't flag waitFor in that same release.

I'm also OK with not flagging it at all, but simply removing it after a couple of releases where we've had the migration options available.

@nex3
Copy link
Member

nex3 commented Apr 21, 2023

This doesn't meet the bar of providing a viable alternative for existing use-cases. Even if this synchronous isolate package addresses Sass's needs—which is still totally hypothetical at this point—it definitely doesn't meet dcli's. You say "the usage of asynchronous dart:io methods can be replaced with synchronous counterparts", but there's no synchronous equivalent of many dart:io features, particularly running a process with interactive access to standard IO which dcli relies heavily on.

A viable alternative for this feature that addresses all its uses looks like fibers, for which there's a considerable amount of prior art of integrating it into evented systems like Dart. But if you're not ready to go there, please leave thing as they are as you said in #39390 (comment).

@mraleph
Copy link
Member Author

mraleph commented Apr 21, 2023

@nex3 Mitigation section provides a number of migration paths which together address all existing uses of waitFor. In my opinion primary migration path for dcli is to convert their code to use await, though other alternatives are also available.

there's no synchronous equivalent of many dart:io features, particularly running a process with interactive access to standard IO which dcli relies heavily on.

Unless I am misunderstanding something this is also addressed by dart:ffi and dart:isolate in the very same way you do it in SASS: simplest approach here is to spawn a worker isolate which uses asynchronous dart:io methods to run a process and handle IO and have this worker isolate communicate back to the main isolate using a synchronous channel built with dart:ffi.

A viable alternative for this feature that addresses all its uses looks like fibers

If we only had native to worry about we would probably already done fibers. Unfortunately JS throws a wrench in this: adding fibers means sacrificing portability.

My current thinking here is that the best we could do without sacrificing portability is to have fibers underneath async-await implementation (so that async-to-async calls become as cheap as normal calls), but that would not allow people to suspend execution across synchronous frames.

This is anyway tangential to the desire to remove waitFor and has different timelines: fibers (even as an implementation detail) might or might not come, but we already have all the tools for current users to migrate of waitFor.

@nex3
Copy link
Member

nex3 commented Apr 21, 2023

I understand that you're eager to get rid of waitFor. It's definitely not the right abstraction for what it's trying to do—I agree with that completely. But please don't let that eagerness translate into putting users into an untenable situation. We all want to find the right alternative here.

"Mitigation" isn't the same thing as a "viable alternative", though. Have you discussed with @bsutton or other maintainers of tools using waitFor to see if they consider this viable? I don't want to put words in their mouth, but I'd be very surprised if they find the prospect of re-implementing and maintaining large dart:io APIs as isolate proxies to be a good solution.

waitFor() provides three important capabilities that are otherwise missing from Dart today:

  1. Allowing async code to be passed as callbacks to synchronous APIs. This is essentially the Sass embedded compiler's use-case.

  2. Providing synchronous access to dart:io APIs that are async-only, such as Process.start, HTTP, sockets, etc. This is dcli's primary use case.

  3. Making it possible to share logic across synchronous and asynchronous APIs. Even when both APIs exist, there's no other way to write code that can operate either synchronously or asynchronously other than copying it and everything it transitively touches. This comes up occasionally for Google-internal scripting.

The proposed solution addresses 1 acceptably, but it doesn't address 2 without a huge amount of additional wrapper work on the part of users and it doesn't address 3 at all. All of these are exacerbated by the fact that "single-threaded" async code is much slower than the equivalent synchronous code even when there's no IO going on.

If we only had native to worry about we would probably already done fibers. Unfortunately JS throws a wrench in this: adding fibers means sacrificing portability.

My expectation would be that Fibers would be a VM-only feature, like waitFor() is today. Everything we're talking about—isolates, dart:io, dart:ffi—is already VM-only anyway, so it seems like it would make sense to give the VM special functionality for interacting with the event loop in more powerful ways.

@bsutton
Copy link

bsutton commented Apr 21, 2023 via email

@incendial
Copy link
Contributor

we still have the problem that the linter doesn't cover all of
the 'you forgot to await x' scenarios which makes writing cli apps using an
async library dangerous.

Do you expect this to be provided by the Dart analyzer / linter or are open to accept external solutions as well?

@bsutton
Copy link

bsutton commented Apr 22, 2023 via email

@incendial
Copy link
Contributor

I view this a fundamental requirement and believe it should be in the dart
linter and in the recommended set of lints in the lints package.

Sorry, but this reads as if your intentions are to get this rule in the linter and the core set, not to find any good option that unblocks the migration. If this is such a problem, why you're focused only on one specific solution?

@bsutton
Copy link

bsutton commented Apr 22, 2023 via email

@incendial
Copy link
Contributor

incendial commented Apr 22, 2023

Fair point. Now I better understand the reasons behind it, thank you.

@vsmenon
Copy link
Member

vsmenon commented Apr 22, 2023

@pq - do we have a pointer to the linter work in this area (unawaited async)?

@timsneath
Copy link
Contributor

@bsutton I'm curious to know -- is there a good list of sync APIs you'd need that might make it easier to migrate from waitFor?

That is, can you expand on @nex3's comment here?

Providing synchronous access to dart:io APIs that are async-only, such as Process.start, HTTP, sockets, etc. This is dcli's primary use case.

In my own package, I can drop waitFor altogether as soon as resolvePackageUriSync is exposed...

@pq
Copy link
Member

pq commented Apr 24, 2023

@bsutton, regarding lint support, would a combination of unawaited_futures and discarded_futures be sufficient? (Assuming false positives are addressed in the latter?)

@mraleph
Copy link
Member Author

mraleph commented Apr 24, 2023

I have spent time trying to understand implications for both https://github.com/sass/dart-sass-embedded and https://github.com/onepub-dev/dcli by eliminating waitFor myself.

dart-sass-embedded

Here is the branch that completely eliminates waitFor from dart-sass-embedded by switching it to an model where a new isolate is spawned for each incoming compilation request.

The main isolate works with stdin/stdout communication channel using asynchronous APIs and then dispatches compilations to worker isolates. When a worker isolate needs to call back to to host they send request back to the main isolate (using a normal SendPort) and suspends execution using native synchronisation primitives. Main isolate will then route response back to the worker isolate once it is received on the stdin.

I think this effectively repeats work that @nex3 and @ntkme have already done previously.

Unsurprisingly it works without any issues (all tests pass).

There is a bit too much serialization / deserialisation going on - which is probably wasteful (especially for large messages like compilation request / responses). This can be addressed by either changing protocol slightly or by changing how we deserialise these messages (protocol buffers allow you to peak inside them based on tag numbers).

My conclusion is that there are really no blockers for Sass here.

dcli

I have started going through dcli as well eliminating waitFor usage (here is snapshot of my changes). I have managed to mostly eliminate waitFor in the code with the exception of few large pieces and tests. The following patterns left unmigrated:

  • Synchronous flushing of stdin and stderr.
  • fetch operation which uses HttpClient
  • hard lock in named_lock which uses binding to port as a locking primitive:
  • process related API (RunnableProcess and Progress)

My current assessment is that for flush (first item) we could probably include builtin synchronous flushing API. The rest can be covered by a helper isolate + blocking synchronization primitives. I have included dcli_core/bin/sync_process.dart as an illustration of how one could run process iteractively and communicate with it synchronously. Though how exactly to refactor these APIs are better decided by the original author.

I have observed that the lion share of waitFor usage in dcli can be eliminated simply by using synchronous counterparts of dart:io asynchronous APIs. Using synchronous API also makes code considerably simpler in many places, when compared to using asynchronous counterparts and waitFor.

So my conclusion for dcli is that same as for Sass - there are no real blockers, though it would be nice to extend dart:io with synchronous flush.

Other uses

I have also used Github Code Search to search for other instances of waitFor and all that I have found is related to resolvePackageUri being async. (Plus a couple uses in code which has not been updated for 3+ years).

@ntkme
Copy link
Contributor

ntkme commented Apr 24, 2023

There is a bit too much serialization / deserialisation going on - which is probably wasteful (especially for large messages like compilation request / responses). This can be addressed by either changing protocol slightly or by changing how we deserialise these messages (protocol buffers allow you to peak inside them based on tag numbers).

Issue for addressing this inefficiency: sass/sass#3579

My conclusion is that there are really no blockers for Sass here.

That's fair, but I suggest to not rush setting timeline for removing waitFor. What we got so far is only a POC that works for linux, we still need to work on porting for Windows, abstract ffi logic as a package, infra and testing, etc. There are tons of todos if we decide to go down this route.

Deprecation can be declared early to suggest new user to not use a to-be removed feature, but obsoletion timeline should only be declared when the alternative solution is production ready. Declare an obsoletion when all the alternative solutions are still just POC is way too aggressive. If Dart team is committed to build the alternative that is needed for migration, I think it won't be too late to talk about obsoletion timeline after you have most developers successfully migrate off the deprecated feature.

@mraleph
Copy link
Member Author

mraleph commented Apr 25, 2023

What we got so far is only a POC that works for linux, we still need to work on porting for Windows, abstract ffi logic as a package, infra and testing, etc. There are tons of todos if we decide to go down this route.

POC from yesterday worked on any POSIX system (originally developed on Mac OS X, but will also work on Linux, iOS and Android). I spend ~1h today abstracting the code a bit and porting it to Windows - which was fairly trivial as well just as one would expect. All dart-sass-embedded tests pass there as well.

Deprecation can be declared early to suggest new user to not use a to-be removed feature, but obsoletion timeline should only be declared when the alternative solution is production ready.

The waitFor was deprecated for more than a year now and we have been talking about removing it for more than 3 years. That neither prevented people from using it, nor did it motivate Sass and DCli to migrate away from it.

My experiments demonstrate without any doubt that Dart already today provides all necessary tools for users to migrate off waitFor in a matter of days by rewriting their code. So I think it would be well within our policies to just remove waitFor in the next stable release. However, I acknowledge that these tools are fairly low-level and possibly too heavyweight for some use-cases (like Isolate.resolvePackageUri), so I am not going to propose such unpleasantly aggressive route and instead set obsoletion date to 1 year from now (3.4), which gives us all plenty of time to migrate.

@nex3
Copy link
Member

nex3 commented Apr 25, 2023

We (the Sass and dcli teams) are trying to be patient and work with the Dart team to ensure that we can find a solution we're all happy with to move forward here. I think we've been quite clear about what the critical parts of the status quo are for us, and we've provided a number of possible solutions to move forward that would satisfy our needs. I don't feel like we're getting the same patience or care from you, @mraleph.

Unilaterally moving the goalposts from "when we have a viable alternative" to a drop-dead date is an aggressive, anti-collaborative tactic. It makes me, as a user, worry that my needs or even commitments made by the Dart team are not relevant at all to the decision-making that actually happens. It also makes me feel like the effort we've put into working with you in good faith to try and find a mutually satisfactory solution was wasted.

This isn't just an academic exercise. There are real people who rely on this software—sass-embedded alone gets 65k downloads a week, and it's part of Google's larger strategic plans with Angular. Creating it was only possible at all because waitFor() existed. Acting like we're naughty children for using it all this time, when the Dart team wasn't putting any effort into providing an alternative, is both unhelpful and insulting. Please: work with us like we're trying to work with you.

@vsmenon
Copy link
Member

vsmenon commented Apr 25, 2023

@nex3 - @mraleph is digging into the code to propose viable alternatives above. We'd all like reasonable off ramps for sass and dcli.

I don't think we need a general purpose alternative such as fibers to move forward. As you've noted, V8 chose to not go that way: https://sass-lang.com/blog/node-fibers-discontinued#the-death-of-fibers

@mraleph
Copy link
Member Author

mraleph commented Apr 26, 2023

@nex3 I am sorry you feel this way. I would like to understand which part of this you don't consider viable. When reading that code you have to assume that Mailbox has a slightly nicer API and lives together with underlying synchronisation primitives in a separate package maintained by the Dart team. My understanding, from discussions on #44804, is that this will be an acceptable compromise. If I missed something - please list these things.

I also encourage you to see timeline from our perspective:

  • The consensus within the Dart team is that we want this experimental feature removed.
  • We have agreed to postpone removal until we have some alternative, we have marked the feature as deprecated to encourage people to move away from it;
  • We have waited;
  • We have found an alternative;
  • We have made PoCs which demonstrate that alternative indeed works (e.g. for Sass it passes all tests on Windows/Linux and Mac OS X);
  • We have committed to package an alternative into a nice package which hides low-level details away from users which don't feel comfortable dealing with low-level code.
  • We have committed to a generous 1 year removal timeline.

copybara-service bot pushed a commit that referenced this issue Jul 11, 2023
TEST=augmented few existing tests

Bug: #52121
CoreLibraryReviewExempt: VM-only change, other platforms don't support this API.
Change-Id: I95decae6cf1a5c6ad694747313aa0dbe0a13025d
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/312981
Reviewed-by: Lasse Nielsen <lrn@google.com>
Commit-Queue: Slava Egorov <vegorov@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
copybara-service bot pushed a commit that referenced this issue Sep 14, 2023
Per breaking change request we are now disabling
waitFor by default.

Users can still enable it by passing the flag:

     --enabled-deprecated-wait-for

Issue #52121

TEST=standalone/io/wait_for_deprecation_test

CoreLibraryReviewExempt: standalone VM only change
Change-Id: Ied78f91344d15cb77e932514e2b752bb6ac5dc5d
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/326021
Commit-Queue: Slava Egorov <vegorov@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
Reviewed-by: Michael Thomsen <mit@google.com>
@mraleph
Copy link
Member Author

mraleph commented Sep 14, 2023

waitFor is now disabled by default on main branch and can be enabled by passing --enabled-deprecated-wait-for to the VM. We are going to fully remove waitFor in 3.4.

@bsutton
Copy link

bsutton commented Sep 15, 2023

I'm simply not going to be able to make this timeline for DCLI.

@nex3
Copy link
Member

nex3 commented Sep 20, 2023

The waitFor() API was disabled, but there's still no synchronous alternative to Isolate.resolvePackageUri. This has broken Dart Sass's release process without a clear avenue for a fix other than pinning ourselves to an old Dart version.

nex3 added a commit to sass/dart-sass that referenced this issue Sep 20, 2023
nex3 added a commit to sass/dart-sass that referenced this issue Sep 20, 2023
@ntkme
Copy link
Contributor

ntkme commented Sep 20, 2023

The waitFor() API was disabled, but there's still no synchronous alternative to Isolate.resolvePackageUri. This has broken Dart Sass's release process without a clear avenue for a fix other than pinning ourselves to an old Dart version.

It is available in dev channel, but it would be tricky to use it conditionally because it is not available in stable: 4fddaf9

@nex3
Copy link
Member

nex3 commented Sep 20, 2023

As @timsneath pointed out in #52121 (comment), it's important to have at least one release that contains Isolate.resolvePackageUriSync() and waitFor() so that users can gracefully transition from the one to the other without being suddenly broken.

@bsutton
Copy link

bsutton commented Sep 20, 2023 via email

Goodwine added a commit to google/dart_cli_pkg that referenced this issue Oct 3, 2023
copybara-service bot pushed a commit that referenced this issue Oct 5, 2023
We are going to enable waitFor in 3.2 release
and disable it in 3.3.

This makes migration smoother for users that need
to use Isolate.resolvePackageUriSync which is
only added in 3.2.

The actual removal timeline remains the same:
we will remove waitFor in 3.4.

TEST=ci

Bug: #52121
Change-Id: I1ab7d07f874b3d914f070f1c358fcffaa96da28b
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/329420
Reviewed-by: Martin Kustermann <kustermann@google.com>
Commit-Queue: Slava Egorov <vegorov@google.com>
Goodwine added a commit to google/dart_cli_pkg that referenced this issue Oct 5, 2023
* Add 'isNodeJs' getter to cli_pkg/js.dart
* Add the 'process' getter to cli_pkg/js.dart
* Add browser tests
* disable dart-dev CI testing due to dart-lang/sdk#52121
copybara-service bot pushed a commit that referenced this issue Oct 5, 2023
We are going to enable waitFor in 3.2 release
and disable it in 3.3.

This makes migration smoother for users that need
to use Isolate.resolvePackageUriSync which is
only added in 3.2.

The actual removal timeline remains the same:
we will remove waitFor in 3.4.

TEST=ci

Bug: #52121
Change-Id: If38376c66e1d6712c3d030a1b4c88f1ab121c204
Cherry-pick: https://dart-review.googlesource.com/c/sdk/+/329420
Cherry-pick-request: #53691
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/329560
Reviewed-by: Martin Kustermann <kustermann@google.com>
@bsutton
Copy link

bsutton commented Oct 5, 2023

Methods that I need sync versions of:

there is a chance that these once aren't needed but more research is required.

StreamController.close(); 
StreamSubscription.close()

These once I don't see a way around.

Stdout.flush
IOSink.flush
``

@mraleph
Copy link
Member Author

mraleph commented Oct 5, 2023

We are definitely not going to add sync methods for StreamController.close() or StreamSubscription.close and IOSink.flush - these are inherently asynchronous.

stdout.flush() does not do anything if you only use stdout.write() and similar - because stdout.write are writing things synchronously (and blocking) into the stdout. The only case when it does something useful is when you do stdout.addStream. So if you avoid addStream then you also don't need stdout.flush.

@bsutton
Copy link

bsutton commented Oct 6, 2023

Any chance that File.createSync(exclusive) could be changed to return true/false based on whether the file was created.

My NamedLock class currently uses a TCP socket as an interprocess locking mechanism as there is no other way to take an interprocess lock.
If File.create returned true then I could use that as a locking mechanism, removing the need to use a TCP socket as a lock and then NamedLock could be synchronous (as god intended).

Alternatively sync methods for:

ServerSocket.bind
socket.close()

would allow me to use the existing TCP socket method but in a sync way.

@mraleph
Copy link
Member Author

mraleph commented Oct 9, 2023

@bsutton One (simplest) solution for NamedLock problem would be to build your own waitFor out of Isolate.run and package:native_synchronization: you create an isolate which is responsible for managing ServerSocket instance and use blocking synchronization primitives in the main isolate to work with it.

Another solution (more involved one) could be to use FFI and implement named lock on top of platform specific named mutex APIs: CreateMutexW on Windows and sem_open (or PTHREAD_PROCESS_SHARED mutexes residing in shared memory) on POSIX OSes.

copybara-service bot pushed a commit that referenced this issue Nov 29, 2023
Revert "[vm] Enable waitFor for 3.2 release"

This reverts commit f8086ed.

R=kustermann@google.com
TEST=covered by existing tests

Bug: #52121
Change-Id: Ic5c7ad9af8ff142564ce237f868dd39354dfd615
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/338761
Reviewed-by: Martin Kustermann <kustermann@google.com>
Commit-Queue: Slava Egorov <vegorov@google.com>
@mraleph mraleph mentioned this issue Jan 5, 2024
@jimmyff
Copy link

jimmyff commented Feb 23, 2024

Hi, I'm using waitFor in a number of cloud build scripts. Could someone please point me in the direction of the best way to migrate this code?

    // testing cloud_functions_core
    final pccGet = waitFor<Process>(Process.start(
      'dart',
      ['test', '--chain-stack-traces'],
      mode: ProcessStartMode.inheritStdio,
      workingDirectory: '../cloud_functions_core',
      environment: {'DOCKER_BUILDKIT': '1'},
    ));
    if (waitFor<int>(pccGet.exitCode) != 0) {
      stderr.writeln('ERROR: Testing failed.');
      exit(1);
    }

Thanks

@julemand101
Copy link
Contributor

@jimmyff
Why are you not using Process.runSync?

@jimmyff
Copy link

jimmyff commented Feb 23, 2024

@jimmyff Why are you not using Process.runSync?

Ah, now I feel silly -that's exactly when I needed. Sorry for noise!

@mraleph
Copy link
Member Author

mraleph commented Feb 29, 2024

The removal is complete.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-library breaking-change-approved breaking-change-request This tracks requests for feedback on breaking changes
Projects
None yet
Development

No branches or pull requests