| 1 | #!/usr/bin/env python2
|
| 2 | """
|
| 3 | exceptions.py
|
| 4 | """
|
| 5 | from __future__ import print_function
|
| 6 |
|
| 7 | #from errno import EISDIR
|
| 8 | import os
|
| 9 | from mycpp.mylib import log, print_stderr
|
| 10 |
|
| 11 | from typing import List, Any
|
| 12 | #import posix_ as posix
|
| 13 |
|
| 14 |
|
| 15 | def Close(fd):
|
| 16 | # type: (int) -> None
|
| 17 |
|
| 18 | #raise OSError(EISDIR)
|
| 19 | raise OSError(0)
|
| 20 |
|
| 21 |
|
| 22 | def Pop(fd):
|
| 23 | # type: (int) -> None
|
| 24 |
|
| 25 | try:
|
| 26 | #posix.close(fd)
|
| 27 | Close(fd)
|
| 28 | except (IOError, OSError) as e:
|
| 29 | #log('Error closing descriptor %d: %s', rf.orig_fd, pyutil.strerror(e))
|
| 30 | log('Error closing descriptor %d', fd)
|
| 31 | raise
|
| 32 |
|
| 33 |
|
| 34 | def AppBundleMain(argv):
|
| 35 | # type: (List[str]) -> int
|
| 36 |
|
| 37 | Pop(3)
|
| 38 |
|
| 39 | return 0
|
| 40 |
|
| 41 |
|
| 42 | def TestRethrow():
|
| 43 | # type: () -> int
|
| 44 | """
|
| 45 | This is fine, the problem was throwing an exceptinon in a DESTRUCTOR
|
| 46 | """
|
| 47 | argv = [] # type: List[str]
|
| 48 |
|
| 49 | try:
|
| 50 | return AppBundleMain(argv)
|
| 51 |
|
| 52 | except ValueError as e:
|
| 53 | return 2
|
| 54 | #except error.Usage as e:
|
| 55 | # #builtin.Help(['oil-usage'], util.GetResourceLoader())
|
| 56 | # log('oil: %s', e.msg)
|
| 57 | # return 2
|
| 58 |
|
| 59 | except KeyboardInterrupt:
|
| 60 | print('')
|
| 61 | return 130 # 128 + 2
|
| 62 |
|
| 63 | except (IOError, OSError) as e:
|
| 64 | if 0:
|
| 65 | import traceback
|
| 66 | traceback.print_exc()
|
| 67 |
|
| 68 | # test this with prlimit --nproc=1 --pid=$$
|
| 69 | #print_stderr('osh I/O error (main): %s' % posix.strerror(e.errno))
|
| 70 | print_stderr('osh I/O error (main)')
|
| 71 | return 2 # dash gives status 2
|
| 72 |
|
| 73 |
|
| 74 | class ctx_TerminalControl(object):
|
| 75 |
|
| 76 | def __init__(self):
|
| 77 | # type: () -> None
|
| 78 |
|
| 79 | log('TerminalControl init')
|
| 80 |
|
| 81 | def __enter__(self):
|
| 82 | # type: () -> None
|
| 83 | pass
|
| 84 |
|
| 85 | def __exit__(self, type, value, traceback):
|
| 86 | # type: (Any, Any, Any) -> None
|
| 87 | log('TerminalControl exit')
|
| 88 |
|
| 89 | TestRethrow()
|
| 90 |
|
| 91 | # https://akrzemi1.wordpress.com/2011/09/21/destructors-that-throw/
|
| 92 |
|
| 93 | # Quote: Until any exception gets out from the destructor we can throw at
|
| 94 | # will inside, even from other destructors, and this does not account for
|
| 95 | # double-exception situation or "throwing from destructor during stack
|
| 96 | # unwinding." Let's illustrate it with an example.
|
| 97 | log('Throw and Catch within destructor seems OK')
|
| 98 |
|
| 99 |
|
| 100 | def TestDestructor():
|
| 101 | # type: () -> None
|
| 102 |
|
| 103 | with ctx_TerminalControl():
|
| 104 | log('hi')
|
| 105 |
|
| 106 |
|
| 107 | def run_tests():
|
| 108 | # type: () -> int
|
| 109 |
|
| 110 | TestRethrow()
|
| 111 |
|
| 112 | log('')
|
| 113 | log('TestDestructor')
|
| 114 | log('')
|
| 115 |
|
| 116 | TestDestructor()
|
| 117 |
|
| 118 | return 0
|
| 119 |
|
| 120 |
|
| 121 | def run_benchmarks():
|
| 122 | # type: () -> None
|
| 123 | raise NotImplementedError()
|
| 124 |
|
| 125 |
|
| 126 | if __name__ == '__main__':
|
| 127 | if os.getenv('BENCHMARK'):
|
| 128 | log('Benchmarking...')
|
| 129 | run_benchmarks()
|
| 130 | else:
|
| 131 | run_tests()
|