summaryrefslogtreecommitdiff
path: root/src/cstore
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 /src/cstore
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.
Diffstat (limited to 'src/cstore')
-rw-r--r--src/cstore/cstore.cpp114
-rw-r--r--src/cstore/cstore.hpp35
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_ */