diff --git a/src/runtime/c/pgf/data.h b/src/runtime/c/pgf/data.h index 5886ab710..7cb4507e1 100644 --- a/src/runtime/c/pgf/data.h +++ b/src/runtime/c/pgf/data.h @@ -30,6 +30,35 @@ private: const char *msg; }; +class PGF_INTERNAL_DECL pgf_systemerror : public std::runtime_error { +public: + pgf_systemerror(int code) : std::runtime_error("pgf_systemerror") + { + this->m_code = code; + this->m_filepath = NULL; + } + + pgf_systemerror(int code, const char *filepath) : std::runtime_error("pgf_systemerror") + { + this->m_code = code; + this->m_filepath = filepath; + } + + virtual int code() const + { + return m_code; + } + + const char *filepath() const + { + return m_filepath; + } + +private: + int m_code; + const char *m_filepath; +}; + struct PGF_INTERNAL_DECL PgfFlag { PgfLiteral value; PgfText name; diff --git a/src/runtime/c/pgf/db.cxx b/src/runtime/c/pgf/db.cxx index 2a6828554..c9d80c61e 100644 --- a/src/runtime/c/pgf/db.cxx +++ b/src/runtime/c/pgf/db.cxx @@ -2,7 +2,6 @@ #include #include #include -#include #include "data.h" @@ -270,30 +269,33 @@ struct malloc_state }; PGF_INTERNAL -PgfDB::PgfDB(const char* pathname, int flags, int mode) { +PgfDB::PgfDB(const char* filepath, int flags, int mode) { size_t file_size; bool is_new = false; fd = -1; ms = NULL; - if (pathname == NULL) { + if (filepath == NULL) { + this->filepath = NULL; file_size = getpagesize(); is_new = true; } else { - fd = open(pathname, flags, mode); + fd = open(filepath, flags, mode); if (fd < 0) - throw std::system_error(errno, std::generic_category()); + throw pgf_systemerror(errno, filepath); + + this->filepath = strdup(filepath); file_size = lseek(fd, 0, SEEK_END); if (file_size == ((off_t) -1)) - throw std::system_error(errno, std::generic_category()); + throw pgf_systemerror(errno, filepath); is_new = false; if (file_size == 0) { file_size = getpagesize(); if (ftruncate(fd, file_size) < 0) - throw std::system_error(errno, std::generic_category()); + throw pgf_systemerror(errno, filepath); is_new = true; } } @@ -302,7 +304,7 @@ PgfDB::PgfDB(const char* pathname, int flags, int mode) { ms = (malloc_state*) mmap(NULL, file_size, PROT_READ | PROT_WRITE, mflags, fd, 0); if (ms == MAP_FAILED) - throw std::system_error(errno, std::generic_category()); + throw pgf_systemerror(errno, filepath); if (is_new) { init_state(file_size); @@ -310,7 +312,7 @@ PgfDB::PgfDB(const char* pathname, int flags, int mode) { int res = pthread_rwlock_init(&rwlock, NULL); if (res != 0) { - throw std::system_error(res, std::generic_category()); + throw pgf_systemerror(errno); } } @@ -327,6 +329,8 @@ PgfDB::~PgfDB() { close(fd); pthread_rwlock_destroy(&rwlock); + + ::free((void*) filepath); } PGF_INTERNAL @@ -338,7 +342,7 @@ void PgfDB::sync() int res = msync((void *) ms, size, MS_SYNC | MS_INVALIDATE); if (res != 0) - throw std::system_error(errno, std::generic_category()); + throw pgf_systemerror(errno); } PGF_INTERNAL @@ -837,13 +841,13 @@ object PgfDB::malloc_internal(size_t bytes) if (fd >= 0) { if (ftruncate(fd, new_size) < 0) - throw std::system_error(errno, std::generic_category()); + throw pgf_systemerror(errno, filepath); } malloc_state* new_ms = (malloc_state*) mremap(ms, old_size, new_size, MREMAP_MAYMOVE); if (new_ms == MAP_FAILED) - throw std::system_error(errno, std::generic_category()); + throw pgf_systemerror(errno); ms = new_ms; current_base = (unsigned char*) ms; @@ -961,7 +965,7 @@ DB_scope::DB_scope(PgfDB *db, DB_scope_mode tp) (tp == READER_SCOPE) ? pthread_rwlock_rdlock(&db->rwlock) : pthread_rwlock_wrlock(&db->rwlock); if (res != 0) - throw std::system_error(res, std::generic_category()); + throw pgf_systemerror(res); save_db = current_db; current_db = db; @@ -978,7 +982,7 @@ DB_scope::~DB_scope() #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wterminate" if (res != 0) - throw std::system_error(res, std::generic_category()); + throw pgf_systemerror(res); #pragma GCC diagnostic pop current_db = save_db; diff --git a/src/runtime/c/pgf/db.h b/src/runtime/c/pgf/db.h index 521bf1fb8..dfb5f0267 100644 --- a/src/runtime/c/pgf/db.h +++ b/src/runtime/c/pgf/db.h @@ -57,6 +57,7 @@ public: class PgfDB { private: int fd; + const char *filepath; malloc_state* ms; pthread_rwlock_t rwlock; @@ -64,7 +65,7 @@ private: friend class PgfReader; public: - PGF_INTERNAL_DECL PgfDB(const char* pathname, int flags, int mode); + PGF_INTERNAL_DECL PgfDB(const char* filepath, int flags, int mode); PGF_INTERNAL_DECL ~PgfDB(); template diff --git a/src/runtime/c/pgf/pgf.cxx b/src/runtime/c/pgf/pgf.cxx index a08ce83a1..5c893a2f3 100644 --- a/src/runtime/c/pgf/pgf.cxx +++ b/src/runtime/c/pgf/pgf.cxx @@ -23,16 +23,15 @@ PgfDB *pgf_read_pgf(const char* fpath, try { db = new PgfDB(NULL, 0, 0); - std::ifstream in(fpath, std::ios::binary); if (in.fail()) { - throw std::system_error(errno, std::generic_category()); + throw pgf_systemerror(errno, fpath); } { DB_scope scope(db, WRITER_SCOPE); - PgfReader rdr(&in); + PgfReader rdr(&in, fpath); ref pgf = rdr.read_pgf(); PgfDB::set_root(pgf); @@ -40,14 +39,16 @@ PgfDB *pgf_read_pgf(const char* fpath, } return db; - } catch (std::system_error& e) { + } catch (pgf_systemerror& e) { err->type = PGF_EXN_SYSTEM_ERROR; - err->code = e.code().value(); + err->code = e.code(); + err->msg = e.filepath(); } catch (pgf_error& e) { err->type = PGF_EXN_PGF_ERROR; err->msg = strdup(e.what()); } +end: if (db != NULL) delete db; @@ -68,13 +69,13 @@ PgfDB *pgf_boot_ngf(const char* pgf_path, const char* ngf_path, std::ifstream in(pgf_path, std::ios::binary); if (in.fail()) { - throw std::system_error(errno, std::generic_category()); + throw pgf_systemerror(errno, pgf_path); } { DB_scope scope(db, WRITER_SCOPE); - PgfReader rdr(&in); + PgfReader rdr(&in, pgf_path); ref pgf = rdr.read_pgf(); db->set_root(pgf); @@ -84,9 +85,10 @@ PgfDB *pgf_boot_ngf(const char* pgf_path, const char* ngf_path, } return db; - } catch (std::system_error& e) { + } catch (pgf_systemerror& e) { err->type = PGF_EXN_SYSTEM_ERROR; - err->code = e.code().value(); + err->code = e.code(); + err->msg = e.filepath(); } catch (pgf_error& e) { err->type = PGF_EXN_PGF_ERROR; err->msg = strdup(e.what()); @@ -135,9 +137,10 @@ PgfDB *pgf_read_ngf(const char *fpath, } return db; - } catch (std::system_error& e) { + } catch (pgf_systemerror& e) { err->type = PGF_EXN_SYSTEM_ERROR; - err->code = e.code().value(); + err->code = e.code(); + err->msg = e.filepath(); } catch (pgf_error& e) { err->type = PGF_EXN_PGF_ERROR; err->msg = strdup(e.what()); @@ -431,9 +434,10 @@ PgfRevision pgf_clone_revision(PgfDB *db, PgfRevision revision, pgf->abstract.cats->ref_count++; return new_pgf.as_object(); - } catch (std::system_error& e) { + } catch (pgf_systemerror& e) { err->type = PGF_EXN_SYSTEM_ERROR; - err->code = e.code().value(); + err->code = e.code(); + err->msg = e.filepath(); } catch (pgf_error& e) { err->type = PGF_EXN_PGF_ERROR; err->msg = strdup(e.what()); @@ -471,9 +475,10 @@ void pgf_create_function(PgfDB *db, PgfRevision revision, namespace_insert(pgf->abstract.funs, absfun); namespace_release(pgf->abstract.funs); pgf->abstract.funs = nmsp; - } catch (std::system_error& e) { + } catch (pgf_systemerror& e) { err->type = PGF_EXN_SYSTEM_ERROR; - err->code = e.code().value(); + err->code = e.code(); + err->msg = e.filepath(); } catch (pgf_error& e) { err->type = PGF_EXN_PGF_ERROR; err->msg = strdup(e.what()); diff --git a/src/runtime/c/pgf/pgf.h b/src/runtime/c/pgf/pgf.h index 8405d8a8f..015bf4f83 100644 --- a/src/runtime/c/pgf/pgf.h +++ b/src/runtime/c/pgf/pgf.h @@ -55,6 +55,7 @@ typedef struct { * - If the exception was caused by external factors such as an error * from a system call, then type will be PGF_EXN_SYSTEM_ERROR and * the field code will contain the value of errno from the C runtime. + * The field msg will be NULL or it may contain a file name. * * - If the exception was caused by factors related to the GF runtime * itself, then the error type is PGF_EXN_PGF_ERROR, and the field diff --git a/src/runtime/c/pgf/reader.cxx b/src/runtime/c/pgf/reader.cxx index 00af469e0..9d72c9c49 100644 --- a/src/runtime/c/pgf/reader.cxx +++ b/src/runtime/c/pgf/reader.cxx @@ -3,9 +3,10 @@ #include #include -PgfReader::PgfReader(std::istream *in) +PgfReader::PgfReader(std::istream *in, const char *filepath) { this->in = in; + this->filepath = filepath; } uint8_t PgfReader::read_uint8() @@ -15,7 +16,7 @@ uint8_t PgfReader::read_uint8() if (in->eof()) throw pgf_error("reached end of file while reading a grammar"); if (in->fail()) - throw std::system_error(errno, std::generic_category()); + throw pgf_systemerror(errno, filepath); return b; } @@ -27,7 +28,7 @@ uint16_t PgfReader::read_u16be() if (in->eof()) throw pgf_error("reached end of file while reading a grammar"); if (in->fail()) - throw std::system_error(errno, std::generic_category()); + throw pgf_systemerror(errno, filepath); return (((uint16_t) buf[0]) << 8 | buf[1]); } @@ -39,7 +40,7 @@ uint64_t PgfReader::read_u64be() if (in->eof()) throw pgf_error("reached end of file while reading a grammar"); if (in->fail()) - throw std::system_error(errno, std::generic_category()); + throw pgf_systemerror(errno, filepath); return (((uint64_t) buf[0]) << 56 | ((uint64_t) buf[1]) << 48 | @@ -95,7 +96,7 @@ object PgfReader::read_name_internal(size_t struct_size) if (in->eof()) throw pgf_error("utf8 decoding error"); if (in->fail()) - throw std::system_error(errno, std::generic_category()); + throw pgf_systemerror(errno, filepath); ptext->text[size] = 0; @@ -131,7 +132,7 @@ object PgfReader::read_text_internal(size_t struct_size) if (in->eof()) throw pgf_error("utf8 decoding error"); if (in->fail()) - throw std::system_error(errno, std::generic_category()); + throw pgf_systemerror(errno, filepath); p += len; } diff --git a/src/runtime/c/pgf/reader.h b/src/runtime/c/pgf/reader.h index 0565ed41d..de335ff96 100644 --- a/src/runtime/c/pgf/reader.h +++ b/src/runtime/c/pgf/reader.h @@ -10,7 +10,7 @@ class PGF_INTERNAL_DECL PgfReader { public: - PgfReader(std::istream *in); + PgfReader(std::istream *in, const char *filepath); uint8_t read_uint8(); uint16_t read_u16be(); @@ -74,6 +74,7 @@ public: private: std::istream *in; + const char* filepath; object read_name_internal(size_t struct_size); object read_text_internal(size_t struct_size); diff --git a/src/runtime/haskell/PGF2.hsc b/src/runtime/haskell/PGF2.hsc index b5ac81c06..5cfcd395c 100644 --- a/src/runtime/haskell/PGF2.hsc +++ b/src/runtime/haskell/PGF2.hsc @@ -69,7 +69,7 @@ readPGF fpath = withCString fpath $ \c_fpath -> alloca $ \p_revision -> mask_ $ do - c_pgf <- withPgfExn fpath (pgf_read_pgf c_fpath p_revision) + c_pgf <- withPgfExn (pgf_read_pgf c_fpath p_revision) c_revision <- peek p_revision fptr1 <- newForeignPtr pgf_free_fptr c_pgf fptr2 <- C.newForeignPtr c_revision (withForeignPtr fptr1 (\c_db -> pgf_free_revision c_db c_revision)) @@ -85,7 +85,7 @@ bootNGF pgf_path ngf_path = withCString ngf_path $ \c_ngf_path -> alloca $ \p_revision -> mask_ $ do - c_pgf <- withPgfExn pgf_path (pgf_boot_ngf c_pgf_path c_ngf_path p_revision) + c_pgf <- withPgfExn (pgf_boot_ngf c_pgf_path c_ngf_path p_revision) c_revision <- peek p_revision fptr1 <- newForeignPtr pgf_free_fptr c_pgf fptr2 <- C.newForeignPtr c_revision (withForeignPtr fptr1 (\c_db -> pgf_free_revision c_db c_revision)) @@ -100,7 +100,7 @@ readNGF fpath = withCString fpath $ \c_fpath -> alloca $ \p_revision -> mask_ $ do - c_db <- withPgfExn fpath (pgf_read_ngf c_fpath p_revision) + c_db <- withPgfExn (pgf_read_ngf c_fpath p_revision) c_revision <- peek p_revision fptr1 <- newForeignPtr pgf_free_fptr c_db fptr2 <- C.newForeignPtr c_revision (withForeignPtr fptr1 (\c_db -> pgf_free_revision c_db c_revision)) @@ -175,7 +175,7 @@ categories p = withForeignPtr (a_db p) $ \c_db -> withForeignPtr (revision p) $ \c_revision -> do (#poke PgfItor, fn) itor fptr - withPgfExn "" (pgf_iter_categories c_db c_revision itor) + withPgfExn (pgf_iter_categories c_db c_revision itor) cs <- readIORef ref return (reverse cs)) where @@ -234,7 +234,7 @@ functions p = withForeignPtr (a_db p) $ \c_db -> withForeignPtr (revision p) $ \c_revision -> do (#poke PgfItor, fn) itor fptr - withPgfExn "" (pgf_iter_functions c_db c_revision itor) + withPgfExn (pgf_iter_functions c_db c_revision itor) fs <- readIORef ref return (reverse fs)) where @@ -255,7 +255,7 @@ functionsByCat p cat = withForeignPtr (a_db p) $ \c_db -> withForeignPtr (revision p) $ \c_revision -> do (#poke PgfItor, fn) itor fptr - withPgfExn "" (pgf_iter_functions_by_cat c_db c_revision c_cat itor) + withPgfExn (pgf_iter_functions_by_cat c_db c_revision c_cat itor) fs <- readIORef ref return (reverse fs)) where diff --git a/src/runtime/haskell/PGF2/FFI.hsc b/src/runtime/haskell/PGF2/FFI.hsc index 450500097..2810fe05c 100644 --- a/src/runtime/haskell/PGF2/FFI.hsc +++ b/src/runtime/haskell/PGF2/FFI.hsc @@ -193,7 +193,7 @@ newtype PGFError = PGFError String instance Exception PGFError -withPgfExn fpath f = +withPgfExn f = allocaBytes (#size PgfExn) $ \c_exn -> do res <- f c_exn ex_type <- (#peek PgfExn, type) c_exn :: IO (#type PgfExnType) @@ -201,7 +201,11 @@ withPgfExn fpath f = (#const PGF_EXN_NONE) -> return res (#const PGF_EXN_SYSTEM_ERROR) -> do errno <- (#peek PgfExn, code) c_exn - ioError (errnoToIOError "readPGF" (Errno errno) Nothing (Just fpath)) + c_msg <- (#peek PgfExn, msg) c_exn + mb_fpath <- if c_msg == nullPtr + then return Nothing + else fmap Just (peekCString c_msg) + ioError (errnoToIOError "readPGF" (Errno errno) Nothing mb_fpath) (#const PGF_EXN_PGF_ERROR) -> do c_msg <- (#peek PgfExn, msg) c_exn msg <- peekCString c_msg diff --git a/src/runtime/haskell/PGF2/Transactions.hsc b/src/runtime/haskell/PGF2/Transactions.hsc index b7700b1db..bbce7dff2 100644 --- a/src/runtime/haskell/PGF2/Transactions.hsc +++ b/src/runtime/haskell/PGF2/Transactions.hsc @@ -42,7 +42,7 @@ modifyPGF :: PGF -> Transaction a -> IO PGF modifyPGF p (Transaction f) = withForeignPtr (a_db p) $ \c_db -> withForeignPtr (revision p) $ \c_revision -> - withPgfExn "" $ \c_exn -> do + withPgfExn $ \c_exn -> do c_revision <- pgf_clone_revision c_db c_revision c_exn ex_type <- (#peek PgfExn, type) c_exn if (ex_type :: (#type PgfExnType)) == (#const PGF_EXN_NONE) diff --git a/src/runtime/python/pypgf.c b/src/runtime/python/pypgf.c index e8903d871..d4576dd31 100644 --- a/src/runtime/python/pypgf.c +++ b/src/runtime/python/pypgf.c @@ -2391,7 +2391,7 @@ pgf_readPGF(PyObject *self, PyObject *args) py_pgf->db = pgf_read_pgf(fpath, &py_pgf->revision, &err); if (err.type == PGF_EXN_SYSTEM_ERROR) { errno = err.code; - PyErr_SetFromErrnoWithFilename(PyExc_IOError, fpath); + PyErr_SetFromErrnoWithFilename(PyExc_IOError, err.msg); Py_DECREF(py_pgf); return NULL; } else if (err.type == PGF_EXN_PGF_ERROR) { @@ -2419,7 +2419,7 @@ pgf_bootNGF(PyObject *self, PyObject *args) py_pgf->db = pgf_boot_ngf(fpath, npath, &py_pgf->revision, &err); if (err.type == PGF_EXN_SYSTEM_ERROR) { errno = err.code; - PyErr_SetFromErrnoWithFilename(PyExc_IOError, npath); + PyErr_SetFromErrnoWithFilename(PyExc_IOError, err.msg); Py_DECREF(py_pgf); return NULL; } else if (err.type == PGF_EXN_PGF_ERROR) { @@ -2446,7 +2446,7 @@ pgf_readNGF(PyObject *self, PyObject *args) py_pgf->db = pgf_read_ngf(fpath, &py_pgf->revision, &err); if (err.type == PGF_EXN_SYSTEM_ERROR) { errno = err.code; - PyErr_SetFromErrnoWithFilename(PyExc_IOError, fpath); + PyErr_SetFromErrnoWithFilename(PyExc_IOError, err.msg); Py_DECREF(py_pgf); return NULL; } else if (err.type == PGF_EXN_PGF_ERROR) {