Opened 4 years ago

Last modified 2 years ago

#5186 new enhancement

Exceptions raised in python error handlers do not propagate

Reported by: lpinner Owned by: hobu
Priority: normal Milestone:
Component: PythonBindings Version: 1.10.0
Severity: normal Keywords: PushErrorHandler
Cc: Even Rouault

Description

GDAL 1.10 on Ubuntu 13.04 and Win 7

Raising an exception within a custom python error handler when set by gdal.PushErrorHandler?(py_function) does not work as expected - the exception gets raised in the function but does not propagate back to the main script. Below is an example to demonstrate:

from osgeo import gdal

def gdal_error_handler(err_class, err_no, err_msg):
    print 'About to raise Exception(%s)'%err_msg
    raise Exception('Raising Exception(%s)'%err_msg)

    print 'We will never see this'

if __name__=='__main__':

    gdal.PushErrorHandler(gdal_error_handler)

    try:
        gdal.Error(gdal.CE_Failure,3,'test error message')
    except:
        print 'gdal.CE_Failure raised an exception'
    else:
        print 'gdal.CE_Failure did not raise an exception'

    gdal.PopErrorHandler()

Output:

About to raise Exception(test error message)
gdal.CE_Failure did not raise an exception

Change History (7)

comment:1 Changed 4 years ago by lpinner

Version: unspecified1.10.0

comment:2 Changed 4 years ago by lpinner

Cc: Even Rouault added

CC'ing Even as he implemented support for custom error handlers in r25663 (#4993)

comment:3 Changed 4 years ago by lpinner

And using a class method as the custom handler segfaults python (Ubuntu 13.04 and Win 7). i.e

from osgeo import gdal

class GdalErrorHandler(object):
    def __init__(self,errorlevel=gdal.CE_Failure):
        self.errorlevel=errorlevel

    def handler(self, err_level, err_no, err_msg):
        if err_level>=self.errorlevel:
            print 'About to raise Exception'
            raise Exception('This is the Exception I expect to see')
        else:
            print 'No exception raised'
            return

        print 'This print statement is never reached as expected'

if __name__=='__main__':

    err=GdalErrorHandler()
    gdal.PushErrorHandler(err.handler)

    try:
        gdal.Error(gdal.CE_Failure,1,'I did not expect to see this error')
    except Exception as e:
        print 'gdal.CE_Failure raised an exception'
        print e
    else:
        print 'gdal.CE_Failure did not raise an exception'

    gdal.PopErrorHandler()

comment:4 Changed 4 years ago by Even Rouault

Type: defectenhancement

The crash was a ref-counting problem that can be workaround by assigning err.handler to a variable before passing it to gdal.PushErrorHandler?()

trunk (r26275) and branches/1.10 (25676) "Python bindings: fix ref-counting of callable passed to gdal.PushErrorHandler?() that could cause segfaults (#5186)"

As far as the propagation of exceptions from the custom error handler to the main code, I'm not sure if this is doable. Looks like it would be some complicated magic... Re-typing that as an enhancement

comment:5 Changed 4 years ago by lpinner

Thanks Even. I've added some info about this to the PythonGotchas wiki page.

comment:6 Changed 2 years ago by Jukka Rahkonen

Can this ticket be closed due to r26275 and r26276 (which I suppose to be the right changeset for branches/1.10)?

comment:7 Changed 2 years ago by lpinner

@jratike80 changes r26275 and r26276 address an issue raised in#comment:3, but don't address the enhancement request that is the main ticket issue - propagation of exceptions from the custom error handler back to the main code.

Though if you/Even want to close as "wontfix", given Even's comments in comment:4 that's ok.

Note: See TracTickets for help on using tickets.