GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — bpo-44938: Expose PyErr_ChainExceptions in the stable API by pablogsal · Pull Request #27799 · python/cpython

Conversation

@pablogsal

@pablogsal pablogsal commented Aug 17, 2021 •
edited by bedevere-bot
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member

https://bugs.python.org/issue44938

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

erlend-aasland reacted with thumbs up emoji
All reactions
  • 👍 1 reaction
@pablogsal
pablogsal requested review from 1st1, asvetlov, brettcannon, encukou, ericsnowcurrently, markshannon, ncoghlan and warsaw as code owners August 17, 2021 17:45
@the-knights-who-say-ni the-knights-who-say-ni added the CLA signed label Aug 17, 2021
@bedevere-bot bedevere-bot added the awaiting core review label Aug 17, 2021
@pablogsal
pablogsal force-pushed the bpo-44938 branch from 8f7c8df to 64d848d Compare August 17, 2021 17:47
1st1
1st1 approved these changes Aug 17, 2021
View reviewed changes
@bedevere-bot bedevere-bot added awaiting merge and removed awaiting core review labels Aug 17, 2021
@pablogsal
bpo-44938: Expose PyErr_ChainExceptions in the stable API
33a859b
@pablogsal
pablogsal force-pushed the bpo-44938 branch from 64d848d to 33a859b Compare August 17, 2021 17:54
@pablogsal
pablogsal requested a review from a team as a code owner August 17, 2021 18:25
@pablogsal
Regenerate limited abi
e9b9724
@pablogsal
pablogsal force-pushed the bpo-44938 branch from bb40a81 to e9b9724 Compare August 17, 2021 18:39
erlend-aasland
erlend-aasland approved these changes Aug 17, 2021
View reviewed changes
iritkatriel
iritkatriel reviewed Aug 17, 2021
View reviewed changes
Comment thread Doc/c-api/exceptions.rst Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Doc/c-api/exceptions.rst Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Doc/c-api/exceptions.rst Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Doc/c-api/exceptions.rst
.. warning::

The caller is responsible for ensuring that this call won't create
any cycles in the exception context chain.

@iritkatriel iritkatriel Aug 17, 2021 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the doc should say what happens if you violate the rule. I think in reality it will just create the cycle and if it doesn't bother you then good for you.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@pablogsal pablogsal Aug 17, 2021

Copy link
Copy Markdown
Member Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the doc should say what happens if you violate the rule.

Is undefined behavior, technically as the contract of this function withing CPython is that cycles should not be created. Some parts of the exception machinery can break (or at least they used to) in presence of cycles.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@iritkatriel iritkatriel Aug 18, 2021

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But when the exception machinery breaks in the presence of a cycle we consider that to be a bug in python.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@encukou encukou Aug 18, 2021

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How is the caller supposed to ensure this? Is there any API for checking it?

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@pablogsal pablogsal Aug 18, 2021

Copy link
Copy Markdown
Member Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no API to check this, but to create a cycle with exceptions it needs to be s deliberate action. There is not an easy way to accidentally crate an exception cycle

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

cjerdonek reacted with thumbs up emoji
All reactions
  • 👍 1 reaction

@cjerdonek cjerdonek Aug 19, 2021

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But when the exception machinery breaks in the presence of a cycle we consider that to be a bug in python.

I think the movement is in the direction of trying to prevent / avoid the creation of cycles in the first place (as was mentioned in the discussion for this recent ticket, for example). The warning being added here is in line with that.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@ncoghlan ncoghlan Sep 9, 2021

Copy link
Copy Markdown
Contributor

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As per my comment below, the easiest way to violate this requirement is to call the API without setting a new exception first (or clearing the existing one). Buggy code (using my API naming suggestion from above):

PyErr_Fetch(&type, &value, &traceback);
// Exception state is not cleared, no new exception is set
PyErr_RestoreOrChain(type, value, traceback); // Sets exception as its own context

Because the exception might not have been instantiated yet when PyErr_Fetch() is called, there's no easy way for the API to reliably detect this error, so the onus is on the caller to manage the exception state correctly.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread Doc/c-api/exceptions.rst Resolved

Uh oh!

There was an error while loading. Please reload this page.

@pablogsal
fixup! Regenerate limited abi
8bcee51
iritkatriel
iritkatriel reviewed Aug 17, 2021
View reviewed changes
Comment thread Doc/c-api/exceptions.rst Resolved

Uh oh!

There was an error while loading. Please reload this page.

pablogsal and others added 2 commits August 18, 2021 00:33
@pablogsal @iritkatriel
Update Doc/c-api/exceptions.rst
a6e7254
Co-authored-by: Irit Katriel <[email protected]>
@pablogsal
fixup! Update Doc/c-api/exceptions.rst
30135a1
iritkatriel
iritkatriel reviewed Aug 17, 2021
View reviewed changes
Comment thread Doc/c-api/exceptions.rst
function behaves as like :c:func:`PyErr_Restore`, but if an exception is
already set, set the provided exception as the context (accessible from
Python through the :attr:`__context__` attribute of the exception) of the
one that is currently set.

@iritkatriel iritkatriel Aug 17, 2021

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't it the other way around - the existing exception becomes the context of the provided exception?

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@pablogsal pablogsal Aug 18, 2021

Copy link
Copy Markdown
Member Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code calls PyException_SetContext(val2, val); where val is the provided one and val2 is the one that is currently set. PyException_SetContext sets the second argument as the context for the first.

So unless I am missing something (is late here 😅 ) this means that "The provided exception (val) becomes the context of the existing exception (val2)"

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@iritkatriel iritkatriel Aug 18, 2021

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, I was thinking we are raising the provided exception in the context of the existing one, but that's what SetObject is for. Can we think of a more descriptive name for this function? I confused the direction, and you confused cause/context because "chain" is ambiguous here.

How about PyErr_RestoreContext? IIUC this describes what you use this function for - putting back a fetched exception, as the context of any exception that happened between the fetch and now. (Should something like the previous sentence be in the doc?)

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@iritkatriel iritkatriel Aug 18, 2021

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or possibly PyErr_RestoreAsContext?

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@pablogsal pablogsal Aug 18, 2021

Copy link
Copy Markdown
Member Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general authors look for "chain" in the docs because that's the action they want to do, so I would really recommend to have "chain" in the name.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

erlend-aasland reacted with thumbs up emoji
All reactions
  • 👍 1 reaction

@iritkatriel iritkatriel Aug 18, 2021

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That may be the case, but I think we should promote clear language, and "chain" in this context is vague. The doc can contain "chain" in the prose for the benefit of people who search for it (for now). But should it be part of the function name for all eternity?

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@pablogsal pablogsal Aug 18, 2021

Copy link
Copy Markdown
Member Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is unclear to me. I agree with the ambiguity but what users if the function want is a higher level approach to the python behaviour: an exception is raised when another exception was there and I want to do in C the same thing as Python does.

I'm not a native speaker do I trust your judgement regarding how ambiguous this sounds and that we need a better name so let's search for one.

Maybe we should make a section in the docs about "exception chaining" and offer two APIs: one for cause and another for context

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@cjerdonek cjerdonek Aug 22, 2021

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@iritkatriel Maybe you can suggest a more specific name that still retains "chain" as part of it?

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@iritkatriel iritkatriel Aug 22, 2021

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The context is an implicitly chained exception (the cause is explicitly chained). There is no need to have both chained and context in the name. If we have only one of them I think it should be context and not chain.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@ncoghlan ncoghlan Sep 9, 2021

Copy link
Copy Markdown
Contributor

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given the equivalence to PyErr_Restore when no exception is currently set, my public naming suggestion would be PyErr_RestoreOrChain, with the shorthand documentation being "Restores the given exception state, or chains it as the exception context if an exception is already set".

The key point to emphasise is that the function takes the same arguments as PyErr_Restore (retrieved from a prior PyErr_Fetch call), and generally does the same thing, but handles currently set exceptions differently: instead of clearing them, it leaves them in place, and "restores" the given exception as the exception context, rather than as the active exception.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
iritkatriel
iritkatriel reviewed Aug 18, 2021
View reviewed changes
Comment thread Doc/c-api/exceptions.rst Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Doc/c-api/exceptions.rst
function behaves as like :c:func:`PyErr_Restore`, but if an exception is
already set, set the provided exception as the context (accessible from
Python through the :attr:`__context__` attribute of the exception) of the
one that is currently set.

@iritkatriel iritkatriel Aug 18, 2021

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, I was thinking we are raising the provided exception in the context of the existing one, but that's what SetObject is for. Can we think of a more descriptive name for this function? I confused the direction, and you confused cause/context because "chain" is ambiguous here.

How about PyErr_RestoreContext? IIUC this describes what you use this function for - putting back a fetched exception, as the context of any exception that happened between the fetch and now. (Should something like the previous sentence be in the doc?)

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread Doc/c-api/exceptions.rst
.. warning::

The caller is responsible for ensuring that this call won't create
any cycles in the exception context chain.

@iritkatriel iritkatriel Aug 18, 2021

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But when the exception machinery breaks in the presence of a cycle we consider that to be a bug in python.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
encukou
encukou reviewed Aug 18, 2021
View reviewed changes
Comment thread Doc/c-api/exceptions.rst
one that is currently set.

The exception type should be a class. Do not pass an invalid exception type
or value. This function steals a reference to each of its arguments in the

@encukou encukou Aug 18, 2021

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could it not steal its arguments?
Functions that don't follow the usual calling convention are harder to reason about; it would be good to treat them as historical exceptions.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@pablogsal pablogsal Aug 18, 2021

Copy link
Copy Markdown
Member Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It steals the arguments because of what it calls. It had the same calling convention as Pyerr_Restore.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

encukou reacted with thumbs up emoji
All reactions
  • 👍 1 reaction

@pablogsal pablogsal Aug 18, 2021

Copy link
Copy Markdown
Member Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, stealing arguments is not an uncommon calling convention.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@ncoghlan ncoghlan Sep 9, 2021

Copy link
Copy Markdown
Contributor

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stealing references is only common because much of the public API was born as internal APIs, and we often try to avoid redundant refcount adjustments in internal APIs.

It took us a long time to realise that stealing references in public APIs makes things confusing for API clients, and can easily lead to double decref bugs (which are more potentially destructive than the object leaks that can arise from missing decref bugs, since deleting objects early can lead to access violations). So I think the new public API should be a wrapper around the internal API that avoids stealing references.

I changed my mind on this point, as PyErr_Fetch and PyErr_Restore are a matched pair. If we go with my PyErr_RestoreOrChain naming suggestion, then the refcounting semantics of the new API should match those of PyErr_Restore (which is to take back the references that PyErr_Fetch created)

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread Doc/c-api/exceptions.rst Resolved

Uh oh!

There was an error while loading. Please reload this page.

Comment thread Doc/c-api/exceptions.rst
.. warning::

The caller is responsible for ensuring that this call won't create
any cycles in the exception context chain.

@encukou encukou Aug 18, 2021

Copy link
Copy Markdown
Member

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How is the caller supposed to ensure this? Is there any API for checking it?

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
pablogsal and others added 2 commits August 18, 2021 12:01
@pablogsal @encukou
Update Doc/c-api/exceptions.rst
9ffb923
Co-authored-by: Petr Viktorin <[email protected]>
@pablogsal @iritkatriel
Update Doc/c-api/exceptions.rst
a102b8f
Co-authored-by: Irit Katriel <[email protected]>
pablogsal
pablogsal commented Aug 18, 2021
View reviewed changes

@pablogsal pablogsal left a comment

Copy link
Copy Markdown
Member Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@encukou @iritkatriel I can remove the sentence but the reality is that this is a contract of the underlying mechanisms, not that much of the function itself. Doing it by hand, which is what extension authors do currently has the same (potential) dangers and is not even documented.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

encukou reacted with thumbs up emoji
All reactions
  • 👍 1 reaction
@brettcannon
brettcannon removed their request for review August 23, 2021 19:15
iceman201
iceman201 approved these changes Sep 5, 2021
View reviewed changes
ncoghlan
ncoghlan requested changes Sep 9, 2021
View reviewed changes

@ncoghlan ncoghlan left a comment

Copy link
Copy Markdown
Contributor

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sticking a "request changes" on this one, as I agree with Serhiy that the API name needs more thought if we're going to make it part of the supported API.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread Doc/c-api/exceptions.rst
one that is currently set.

The exception type should be a class. Do not pass an invalid exception type
or value. This function steals a reference to each of its arguments in the

@ncoghlan ncoghlan Sep 9, 2021

Copy link
Copy Markdown
Contributor

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stealing references is only common because much of the public API was born as internal APIs, and we often try to avoid redundant refcount adjustments in internal APIs.

It took us a long time to realise that stealing references in public APIs makes things confusing for API clients, and can easily lead to double decref bugs (which are more potentially destructive than the object leaks that can arise from missing decref bugs, since deleting objects early can lead to access violations). So I think the new public API should be a wrapper around the internal API that avoids stealing references.

I changed my mind on this point, as PyErr_Fetch and PyErr_Restore are a matched pair. If we go with my PyErr_RestoreOrChain naming suggestion, then the refcounting semantics of the new API should match those of PyErr_Restore (which is to take back the references that PyErr_Fetch created)

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread Doc/c-api/exceptions.rst
function behaves as like :c:func:`PyErr_Restore`, but if an exception is
already set, set the provided exception as the context (accessible from
Python through the :attr:`__context__` attribute of the exception) of the
one that is currently set.

@ncoghlan ncoghlan Sep 9, 2021

Copy link
Copy Markdown
Contributor

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given the equivalence to PyErr_Restore when no exception is currently set, my public naming suggestion would be PyErr_RestoreOrChain, with the shorthand documentation being "Restores the given exception state, or chains it as the exception context if an exception is already set".

The key point to emphasise is that the function takes the same arguments as PyErr_Restore (retrieved from a prior PyErr_Fetch call), and generally does the same thing, but handles currently set exceptions differently: instead of clearing them, it leaves them in place, and "restores" the given exception as the exception context, rather than as the active exception.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread Doc/c-api/exceptions.rst
/* ... code that might produce other errors ... */

/* Set the original exception as the context for the new exception, and set the new exception as the current exception */
PyErr_ChainExceptions(type, value, traceback);

@ncoghlan ncoghlan Sep 9, 2021

Copy link
Copy Markdown
Contributor

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This example is misleading, as if the code doesn't set a new exception, the fetched exception will end up being chained with itself instead of being restored. To safely invoke the new API unconditionally, the code needs to look like this:

    /* Fetch and clear the original exception */
    PyErr_Fetch(&type, &value, &traceback);
    PyErr_Clear();

    /* ... code that might produce other errors ... */

    /* Either restore the original exception, or set it as the context for any new exception */
    PyErr_RestoreOrChain(type, value, traceback);

Skipping the PyErr_Clear() call is only OK if the code definitely sets a new active exception.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread Doc/c-api/exceptions.rst
.. warning::

The caller is responsible for ensuring that this call won't create
any cycles in the exception context chain.

@ncoghlan ncoghlan Sep 9, 2021

Copy link
Copy Markdown
Contributor

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As per my comment below, the easiest way to violate this requirement is to call the API without setting a new exception first (or clearing the existing one). Buggy code (using my API naming suggestion from above):

PyErr_Fetch(&type, &value, &traceback);
// Exception state is not cleared, no new exception is set
PyErr_RestoreOrChain(type, value, traceback); // Sets exception as its own context

Because the exception might not have been instantiated yet when PyErr_Fetch() is called, there's no easy way for the API to reliably detect this error, so the onus is on the caller to manage the exception state correctly.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@bedevere-bot bedevere-bot added awaiting changes and removed awaiting merge labels Sep 9, 2021
@bedevere-bot

bedevere-bot commented Sep 9, 2021

Copy link
Copy Markdown

When you're done making the requested changes, leave the comment: I have made the requested changes; please review again.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@encukou encukou mentioned this pull request Sep 26, 2021
C fixups moderngl/moderngl#479
Merged
@ezio-melotti ezio-melotti removed the CLA signed label Jul 13, 2022
@pablogsal

pablogsal commented Feb 13, 2025

Copy link
Copy Markdown
Member Author

Unfortunately I am abandoning this PR

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@pablogsal pablogsal closed this Feb 13, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@encukou encukou encukou left review comments
@iritkatriel iritkatriel iritkatriel left review comments
@ncoghlan ncoghlan ncoghlan requested changes
@1st1 1st1 1st1 approved these changes
@erlend-aasland erlend-aasland erlend-aasland approved these changes
@asvetlov asvetlov Awaiting requested review from asvetlov asvetlov is a code owner
@ericsnowcurrently ericsnowcurrently Awaiting requested review from ericsnowcurrently ericsnowcurrently is a code owner
@markshannon markshannon Awaiting requested review from markshannon markshannon is a code owner
@warsaw warsaw Awaiting requested review from warsaw warsaw is a code owner
+2 more reviewers
@cjerdonek cjerdonek cjerdonek left review comments
@iceman201 iceman201 iceman201 approved these changes
Reviewers whose approvals may not affect merge requirements

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

awaiting changes

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

11 participants

@pablogsal @bedevere-bot @1st1 @encukou @cjerdonek @ncoghlan @iritkatriel @iceman201 @erlend-aasland @the-knights-who-say-ni @ezio-melotti
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402520 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.