diff options
author | An-Cheng Huang <ancheng@vyatta.com> | 2010-12-13 15:15:09 -0800 |
---|---|---|
committer | An-Cheng Huang <ancheng@vyatta.com> | 2010-12-13 15:15:09 -0800 |
commit | d8ea4f87e3e5a44985f961a2def83612b5c90c9a (patch) | |
tree | 966c0f5d7c1d8c98d83c09c9fb5dcf14afab92ea /src/cstore | |
parent | ab2f5d520eb46a6f407c396413523256803814fe (diff) | |
download | vyatta-cfg-d8ea4f87e3e5a44985f961a2def83612b5c90c9a.tar.gz vyatta-cfg-d8ea4f87e3e5a44985f961a2def83612b5c90c9a.zip |
make the library croak when internal error occurs in perl context.
* extend output/assert mechanism and simplify code.
* when handling internal error, automatically detect perl context and croak if the library is used from perl.
Diffstat (limited to 'src/cstore')
-rw-r--r-- | src/cstore/cstore.cpp | 114 | ||||
-rw-r--r-- | src/cstore/cstore.hpp | 35 |
2 files changed, 111 insertions, 38 deletions
diff --git a/src/cstore/cstore.cpp b/src/cstore/cstore.cpp index 0ff8ba2..2aefed6 100644 --- a/src/cstore/cstore.cpp +++ b/src/cstore/cstore.cpp @@ -1929,11 +1929,16 @@ Cstore::output_user(const char *fmt, ...) { va_list alist; va_start(alist, fmt); - if (out_stream) { - vfprintf(out_stream, fmt, alist); - } else { - vprintf(fmt, alist); - } + voutput_user(out_stream, stdout, fmt, alist); + va_end(alist); +} + +void +Cstore::output_user_err(const char *fmt, ...) +{ + va_list alist; + va_start(alist, fmt); + voutput_user(err_stream, stderr, fmt, alist); va_end(alist); } @@ -1942,29 +1947,30 @@ Cstore::output_internal(const char *fmt, ...) { va_list alist; va_start(alist, fmt); + voutput_internal(fmt, alist); + va_end(alist); +} - int fdout = -1; - FILE *fout = NULL; - do { - if ((fdout = open(C_LOGFILE_STDOUT.c_str(), - O_WRONLY | O_CREAT, 0660)) == -1) { - break; - } - if (lseek(fdout, 0, SEEK_END) == ((off_t) -1)) { - break; - } - if ((fout = fdopen(fdout, "a")) == NULL) { - break; - } - vfprintf(fout, fmt, alist); - } while (0); +void +Cstore::exit_internal(const char *fmt, ...) +{ + va_list alist; + va_start(alist, fmt); + vexit_internal(fmt, alist); va_end(alist); - if (fout) { - fclose(fout); - // fdout is implicitly closed - } else if (fdout >= 0) { - close(fdout); +} + +void +Cstore::assert_internal(bool cond, const char *fmt, ...) +{ + if (cond) { + return; } + + va_list alist; + va_start(alist, fmt); + vexit_internal(fmt, alist); + va_end(alist); } @@ -2872,3 +2878,61 @@ Cstore::print_str_vec(const char *pre, const char *post, output_user("%s", post); } +void +Cstore::voutput_user(FILE *out, FILE *dout, const char *fmt, va_list alist) +{ + if (out) { + vfprintf(out, fmt, alist); + } else if (dout) { + vfprintf(dout, fmt, alist); + } else { + vprintf(fmt, alist); + } +} + +void +Cstore::voutput_internal(const char *fmt, va_list alist) +{ + int fdout = -1; + FILE *fout = NULL; + do { + if ((fdout = open(C_LOGFILE_STDOUT.c_str(), + O_WRONLY | O_CREAT, 0660)) == -1) { + break; + } + if (lseek(fdout, 0, SEEK_END) == ((off_t) -1)) { + break; + } + if ((fout = fdopen(fdout, "a")) == NULL) { + break; + } + vfprintf(fout, fmt, alist); + } while (0); + if (fout) { + fclose(fout); + // fdout is implicitly closed + } else if (fdout >= 0) { + close(fdout); + } +} + +void +Cstore::vexit_internal(const char *fmt, va_list alist) +{ + char buf[256]; + vsnprintf(buf, 256, fmt, alist); + output_internal("%s\n", buf); + if (Perl_get_context()) { + /* we're in a perl context. do a croak to provide more information. + * note that the message should not end in "\n", or the croak message + * will be truncated for some reason. + */ + Perl_croak_nocontext("%s", buf); + // does not return + } else { + // output error message and exit + output_user_err("%s\n", buf); + exit(1); + } +} + diff --git a/src/cstore/cstore.hpp b/src/cstore/cstore.hpp index 872fe1e..9a039af 100644 --- a/src/cstore/cstore.hpp +++ b/src/cstore/cstore.hpp @@ -16,26 +16,27 @@ #ifndef _CSTORE_H_ #define _CSTORE_H_ +#include <cstdarg> #include <vector> #include <string> #include <tr1/unordered_map> #include <cli_cstore.h> -#define exit_internal(fmt, args...) do \ - { \ - output_internal("[%s:%d] " fmt, __FILE__, __LINE__ , ##args); \ - exit(-1); \ - } while (0); +/* declare perl internal functions. just need these two so don't include + * all the perl headers. + */ +extern "C" void Perl_croak_nocontext(const char* pat, ...) + __attribute__((noreturn)) + __attribute__((format(__printf__,1,2))) + __attribute__((nonnull(1))); + +extern "C" void* Perl_get_context(void) + __attribute__((warn_unused_result)); -#define ASSERT_IN_SESSION do \ - { \ - if (!inSession()) { \ - output_user("Internal error: calling %s() without config session\n", \ - __func__); \ - exit_internal("calling %s() without config session\n", __func__); \ - } \ - } while (0); +#define ASSERT_IN_SESSION assert_internal(inSession(), \ + "calling %s() without config session", \ + __func__); /* macros for saving/restoring paths. @@ -300,7 +301,10 @@ public: protected: ////// functions for subclasses void output_user(const char *fmt, ...); + void output_user_err(const char *fmt, ...); void output_internal(const char *fmt, ...); + void exit_internal(const char *fmt, ...); + void assert_internal(bool cond, const char *fmt, ...); private: ////// member class @@ -480,6 +484,11 @@ private: void shell_escape_squotes(string& str); void print_str_vec(const char *pre, const char *post, const vector<string>& vec, const char *quote); + + // output functions + void voutput_user(FILE *out, FILE *dout, const char *fmt, va_list alist); + void voutput_internal(const char *fmt, va_list alist); + void vexit_internal(const char *fmt, va_list alist); }; #endif /* _CSTORE_H_ */ |