2

I have a C++ library which uses glog CHECK statements to asset various conditions on runtime. If a CHECK fails, glog terminates the program. My python program needs some functions from this C++ library, so I have written a simple C wrapper for those functions and compiled a dll, which I can load and use using ctypes.

The problem is, if a CHECK statement fails, the python program is immediately aborted and the user loses all unsaved work!

Instead I would like to handle cases where something went wrong in the library as exceptions in python. The C++ library is not written by me and rewriting it is not a good solution. How can I prevent my python program from being terminated when a glog CHECK statement fails in the C++ library called from it?

Steve
  • 374
  • 1
  • 4
  • 13
  • Maybe re-define `CHECK` to raise Python exceptions and rebuild it? – tadman Jul 31 '17 at 15:51
  • @tadman There are many variations in `glog` which can trigger the same problem. `CHECK_NOTNULL`, `CHECK_STRCASENE`, `LOG(FATAL`, `LOG_IF(FATAL`, `DLOG`, `PLOG`, `SYSLOG`, etc. It would be technically possible to redefine them all but that feels overcomplicated and is problematic to maintain. – Steve Jul 31 '17 at 16:19
  • If your library is full of bombs that might go off there's really only one way to deal with it: Go in there and disarm them all. I don't know what else to say. Honestly shipping code with `assert()` type calls in a non-dev build is a jerk thing to do. These should return errors or exceptions as that's how code is supposed to work, and it would make your life a lot easier. – tadman Jul 31 '17 at 16:21
  • `glog` supports custom error handling via `InstallFailureFunction` call. – user58697 Jul 31 '17 at 22:20
  • @user58697 I have been playing around with `InstallFailureFunction` but I haven't found a way to use it to get around this problem. If I don't terminate the program inside the failure function the program will be terminated after the function anyways. – Steve Aug 01 '17 at 10:48

1 Answers1

0

A quick solution is to run the function in a separate process. The function in the C++ library is heavy (~1 second), so this may be justified.

Minimal Python 3 example:

import ctypes
import multiprocessing

library = ctypes.cdll.LoadLibrary(...)

def RunFunction(params, queue):
    queue.put(library.function(*params))

if __name__ == '__main__': 
    params = ...
    queue = multiprocessing.Queue()
    p = multiprocessing.Process(target=RunFunction, args=(params, queue))
    p.start()
    p.join()
    if p.exitcode == 0:
        print("Function returned: {}".format(queue.get()))
    else:
        print("Non-zero exit code: {}".format(p.exitcode))
Steve
  • 374
  • 1
  • 4
  • 13