Implemented optional C++ exceptions in Error class
These can be activated using the -DLAMMPS_EXCEPTIONS compiler flag. It has no effect for regular execution. However, while using it as a library, any issued command will capture the exception and save its error message. This can be queried using the lammps_has_error() and lammps_get_last_error_message() methods. The Python wrapper checks these in order to rethrow these errors as Python exceptions. See issue #146. (cherry picked from commit 6c154bb0b67a13d38968bc42d31013b97f87db75)
This commit is contained in:
@ -150,6 +150,11 @@ class lammps(object):
|
|||||||
if cmd: cmd = cmd.encode()
|
if cmd: cmd = cmd.encode()
|
||||||
self.lib.lammps_command(self.lmp,cmd)
|
self.lib.lammps_command(self.lmp,cmd)
|
||||||
|
|
||||||
|
if self.lib.lammps_has_error(self.lmp):
|
||||||
|
sb = create_string_buffer(100)
|
||||||
|
self.lib.lammps_get_last_error_message(self.lmp, sb, 100)
|
||||||
|
raise Exception(sb.value.decode().strip())
|
||||||
|
|
||||||
def extract_global(self,name,type):
|
def extract_global(self,name,type):
|
||||||
if name: name = name.encode()
|
if name: name = name.encode()
|
||||||
if type == 0:
|
if type == 0:
|
||||||
|
|||||||
@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
#include <mpi.h>
|
#include <mpi.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "universe.h"
|
#include "universe.h"
|
||||||
#include "output.h"
|
#include "output.h"
|
||||||
@ -21,7 +22,7 @@ using namespace LAMMPS_NS;
|
|||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
Error::Error(LAMMPS *lmp) : Pointers(lmp) {}
|
Error::Error(LAMMPS *lmp) : Pointers(lmp), last_error_message(NULL) {}
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------
|
/* ----------------------------------------------------------------------
|
||||||
called by all procs in universe
|
called by all procs in universe
|
||||||
@ -47,8 +48,14 @@ void Error::universe_all(const char *file, int line, const char *str)
|
|||||||
}
|
}
|
||||||
if (universe->ulogfile) fclose(universe->ulogfile);
|
if (universe->ulogfile) fclose(universe->ulogfile);
|
||||||
|
|
||||||
|
#ifdef LAMMPS_EXCEPTIONS
|
||||||
|
char msg[100];
|
||||||
|
sprintf(msg, "ERROR: %s (%s:%d)\n", str, file, line);
|
||||||
|
throw LAMMPSException(msg);
|
||||||
|
#else
|
||||||
MPI_Finalize();
|
MPI_Finalize();
|
||||||
exit(1);
|
exit(1);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------
|
/* ----------------------------------------------------------------------
|
||||||
@ -61,7 +68,14 @@ void Error::universe_one(const char *file, int line, const char *str)
|
|||||||
if (universe->uscreen)
|
if (universe->uscreen)
|
||||||
fprintf(universe->uscreen,"ERROR on proc %d: %s (%s:%d)\n",
|
fprintf(universe->uscreen,"ERROR on proc %d: %s (%s:%d)\n",
|
||||||
universe->me,str,file,line);
|
universe->me,str,file,line);
|
||||||
|
|
||||||
|
#ifdef LAMMPS_EXCEPTIONS
|
||||||
|
char msg[100];
|
||||||
|
sprintf(msg, "ERROR: %s (%s:%d)\n", str, file, line);
|
||||||
|
throw LAMMPSAbortException(msg, universe->uworld);
|
||||||
|
#else
|
||||||
MPI_Abort(universe->uworld,1);
|
MPI_Abort(universe->uworld,1);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------
|
/* ----------------------------------------------------------------------
|
||||||
@ -95,6 +109,16 @@ void Error::all(const char *file, int line, const char *str)
|
|||||||
if (logfile) fprintf(logfile,"ERROR: %s (%s:%d)\n",str,file,line);
|
if (logfile) fprintf(logfile,"ERROR: %s (%s:%d)\n",str,file,line);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef LAMMPS_EXCEPTIONS
|
||||||
|
char msg[100];
|
||||||
|
sprintf(msg, "ERROR: %s (%s:%d)\n", str, file, line);
|
||||||
|
|
||||||
|
if (universe->nworlds > 1) {
|
||||||
|
throw LAMMPSAbortException(msg, universe->uworld);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw LAMMPSException(msg);
|
||||||
|
#else
|
||||||
if (output) delete output;
|
if (output) delete output;
|
||||||
if (screen && screen != stdout) fclose(screen);
|
if (screen && screen != stdout) fclose(screen);
|
||||||
if (logfile) fclose(logfile);
|
if (logfile) fclose(logfile);
|
||||||
@ -102,6 +126,7 @@ void Error::all(const char *file, int line, const char *str)
|
|||||||
if (universe->nworlds > 1) MPI_Abort(universe->uworld,1);
|
if (universe->nworlds > 1) MPI_Abort(universe->uworld,1);
|
||||||
MPI_Finalize();
|
MPI_Finalize();
|
||||||
exit(1);
|
exit(1);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------
|
/* ----------------------------------------------------------------------
|
||||||
@ -121,7 +146,14 @@ void Error::one(const char *file, int line, const char *str)
|
|||||||
if (universe->uscreen)
|
if (universe->uscreen)
|
||||||
fprintf(universe->uscreen,"ERROR on proc %d: %s (%s:%d)\n",
|
fprintf(universe->uscreen,"ERROR on proc %d: %s (%s:%d)\n",
|
||||||
universe->me,str,file,line);
|
universe->me,str,file,line);
|
||||||
|
|
||||||
|
#ifdef LAMMPS_EXCEPTIONS
|
||||||
|
char msg[100];
|
||||||
|
sprintf(msg, "ERROR on proc %d: %s (%s:%d)\n", me, str, file, line);
|
||||||
|
throw LAMMPSAbortException(msg, world);
|
||||||
|
#else
|
||||||
MPI_Abort(world,1);
|
MPI_Abort(world,1);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------
|
/* ----------------------------------------------------------------------
|
||||||
@ -165,3 +197,31 @@ void Error::done(int status)
|
|||||||
MPI_Finalize();
|
MPI_Finalize();
|
||||||
exit(status);
|
exit(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
return the last error message reported by LAMMPS (only used if
|
||||||
|
compiled with -DLAMMPS_EXCEPTIONS)
|
||||||
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
char * Error::get_last_error() const
|
||||||
|
{
|
||||||
|
return last_error_message;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
set the last error message (only used if compiled with
|
||||||
|
-DLAMMPS_EXCEPTIONS)
|
||||||
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void Error::set_last_error(const char * msg)
|
||||||
|
{
|
||||||
|
delete [] last_error_message;
|
||||||
|
|
||||||
|
if(msg) {
|
||||||
|
last_error_message = new char[strlen(msg)+1];
|
||||||
|
strcpy(last_error_message, msg);
|
||||||
|
} else {
|
||||||
|
last_error_message = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
34
src/error.h
34
src/error.h
@ -15,10 +15,41 @@
|
|||||||
#define LMP_ERROR_H
|
#define LMP_ERROR_H
|
||||||
|
|
||||||
#include "pointers.h"
|
#include "pointers.h"
|
||||||
|
#include <string>
|
||||||
|
#include <exception>
|
||||||
|
|
||||||
namespace LAMMPS_NS {
|
namespace LAMMPS_NS {
|
||||||
|
|
||||||
|
class LAMMPSException : public std::exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::string message;
|
||||||
|
|
||||||
|
LAMMPSException(std::string msg) : message(msg) {
|
||||||
|
}
|
||||||
|
|
||||||
|
~LAMMPSException() throw() {
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual const char * what() const throw() {
|
||||||
|
return message.c_str();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class LAMMPSAbortException : public LAMMPSException {
|
||||||
|
public:
|
||||||
|
MPI_Comm universe;
|
||||||
|
|
||||||
|
LAMMPSAbortException(std::string msg, MPI_Comm universe) :
|
||||||
|
LAMMPSException(msg),
|
||||||
|
universe(universe)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class Error : protected Pointers {
|
class Error : protected Pointers {
|
||||||
|
char * last_error_message;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Error(class LAMMPS *);
|
Error(class LAMMPS *);
|
||||||
|
|
||||||
@ -31,6 +62,9 @@ class Error : protected Pointers {
|
|||||||
void warning(const char *, int, const char *, int = 1);
|
void warning(const char *, int, const char *, int = 1);
|
||||||
void message(const char *, int, const char *, int = 1);
|
void message(const char *, int, const char *, int = 1);
|
||||||
void done(int = 0); // 1 would be fully backwards compatible
|
void done(int = 0); // 1 would be fully backwards compatible
|
||||||
|
|
||||||
|
char * get_last_error() const;
|
||||||
|
void set_last_error(const char * msg);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -108,8 +108,15 @@ void lammps_file(void *ptr, char *str)
|
|||||||
|
|
||||||
char *lammps_command(void *ptr, char *str)
|
char *lammps_command(void *ptr, char *str)
|
||||||
{
|
{
|
||||||
LAMMPS *lmp = (LAMMPS *) ptr;
|
LAMMPS * lmp = (LAMMPS *) ptr;
|
||||||
return lmp->input->one(str);
|
Error * error = lmp->error;
|
||||||
|
|
||||||
|
try {
|
||||||
|
return lmp->input->one(str);
|
||||||
|
} catch(LAMMPSException & e) {
|
||||||
|
error->set_last_error(e.message.c_str());
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------
|
/* ----------------------------------------------------------------------
|
||||||
@ -593,3 +600,29 @@ void lammps_scatter_atoms(void *ptr, char *name,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
Check if a new error message
|
||||||
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
int lammps_has_error(void *ptr) {
|
||||||
|
LAMMPS * lmp = (LAMMPS *) ptr;
|
||||||
|
Error * error = lmp->error;
|
||||||
|
return error->get_last_error() ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------
|
||||||
|
Copy the last error message of LAMMPS into a character buffer
|
||||||
|
------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
int lammps_get_last_error_message(void *ptr, char * buffer, int buffer_size) {
|
||||||
|
LAMMPS * lmp = (LAMMPS *) ptr;
|
||||||
|
Error * error = lmp->error;
|
||||||
|
|
||||||
|
if(error->get_last_error()) {
|
||||||
|
strncpy(buffer, error->get_last_error(), buffer_size-1);
|
||||||
|
error->set_last_error(NULL);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|||||||
@ -45,6 +45,9 @@ int lammps_get_natoms(void *);
|
|||||||
void lammps_gather_atoms(void *, char *, int, int, void *);
|
void lammps_gather_atoms(void *, char *, int, int, void *);
|
||||||
void lammps_scatter_atoms(void *, char *, int, int, void *);
|
void lammps_scatter_atoms(void *, char *, int, int, void *);
|
||||||
|
|
||||||
|
int lammps_has_error(void *);
|
||||||
|
int lammps_get_last_error_message(void *, char *, int);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
17
src/main.cpp
17
src/main.cpp
@ -14,7 +14,9 @@
|
|||||||
#include <mpi.h>
|
#include <mpi.h>
|
||||||
#include "lammps.h"
|
#include "lammps.h"
|
||||||
#include "input.h"
|
#include "input.h"
|
||||||
|
#include "error.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
using namespace LAMMPS_NS;
|
using namespace LAMMPS_NS;
|
||||||
|
|
||||||
@ -26,11 +28,22 @@ int main(int argc, char **argv)
|
|||||||
{
|
{
|
||||||
MPI_Init(&argc,&argv);
|
MPI_Init(&argc,&argv);
|
||||||
|
|
||||||
|
#ifdef LAMMPS_EXCEPTIONS
|
||||||
|
try {
|
||||||
|
LAMMPS *lammps = new LAMMPS(argc,argv,MPI_COMM_WORLD);
|
||||||
|
lammps->input->file();
|
||||||
|
delete lammps;
|
||||||
|
} catch(LAMMPSAbortException & ae) {
|
||||||
|
MPI_Abort(ae.universe, 1);
|
||||||
|
} catch(LAMMPSException & e) {
|
||||||
|
MPI_Finalize();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
#else
|
||||||
LAMMPS *lammps = new LAMMPS(argc,argv,MPI_COMM_WORLD);
|
LAMMPS *lammps = new LAMMPS(argc,argv,MPI_COMM_WORLD);
|
||||||
|
|
||||||
lammps->input->file();
|
lammps->input->file();
|
||||||
delete lammps;
|
delete lammps;
|
||||||
|
#endif
|
||||||
MPI_Barrier(MPI_COMM_WORLD);
|
MPI_Barrier(MPI_COMM_WORLD);
|
||||||
MPI_Finalize();
|
MPI_Finalize();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user