summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAn-Cheng Huang <ancheng@vyatta.com>2010-12-13 15:15:09 -0800
committerAn-Cheng Huang <ancheng@vyatta.com>2010-12-13 15:15:09 -0800
commitd8ea4f87e3e5a44985f961a2def83612b5c90c9a (patch)
tree966c0f5d7c1d8c98d83c09c9fb5dcf14afab92ea
parentab2f5d520eb46a6f407c396413523256803814fe (diff)
downloadvyatta-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.
-rw-r--r--Makefile.am1
-rw-r--r--src/cli_cstore.h1
-rw-r--r--src/cstore/cstore.cpp114
-rw-r--r--src/cstore/cstore.hpp35
4 files changed, 113 insertions, 38 deletions
diff --git a/Makefile.am b/Makefile.am
index bc4bb78..a932d5e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -30,6 +30,7 @@ src_libvyatta_cfg_la_LIBADD += /usr/lib/libgio-2.0.la
src_libvyatta_cfg_la_LIBADD += -lboost_system
src_libvyatta_cfg_la_LIBADD += -lboost_filesystem
src_libvyatta_cfg_la_LIBADD += -lapt-pkg
+src_libvyatta_cfg_la_LIBADD += -lperl
src_libvyatta_cfg_la_LDFLAGS = -version-info 1:0:0
src_libvyatta_cfg_la_SOURCES = src/cli_parse.y src/cli_def.l src/cli_val.l
src_libvyatta_cfg_la_SOURCES += src/cli_new.c src/cli_path_utils.c
diff --git a/src/cli_cstore.h b/src/cli_cstore.h
index c03bddf..54da657 100644
--- a/src/cli_cstore.h
+++ b/src/cli_cstore.h
@@ -116,6 +116,7 @@ typedef struct {
/* extern variables */
extern void *var_ref_handle;
extern FILE *out_stream;
+extern FILE *err_stream;
/* note that some functions may be used outside the actual CLI operations,
* so output may not have been initialized. nop in such cases.
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_ */