On 08/12/2011 08:01 PM, Dhaval Giani wrote:
> On Fri, Aug 12, 2011 at 4:04 AM, Jan Safranek <jsafr...@redhat.com> wrote:
>> Anyway, any other suggestion? YY_FATAL_ERROR *must* stop other
>> processing, otherwise we get sigsegv, which is IMHO worse than exit().
>>
> 
> Unfortunately, I cannot think of something better right now. Propagate
> some error which will stop all sort of processing?

The macro does not know if the function where it's used shold return void or int
or whatever. What about setjmp/longjmp voodoo?

---- 8< ----

The error macro should stop all processing, otherwise some NULL pointers might
get dereferenced (e.g. lex.c:1323). It uses setjmp/longjmp to return from
depths of the bison/lex routines. As obvious consequence, all memory allocated
in the parsers is lost and is never freed. Still, it should be better than
exit() I proposed before.

Signed-off-by: Jan Safranek <jsafr...@redhat.com>
---

 src/config.c             |   12 +++++++++++-
 src/lex.l                |    7 ++++++-
 src/libcgroup-internal.h |    6 ++++++
 3 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/src/config.c b/src/config.c
index fc4901f..c7135aa 100644
--- a/src/config.c
+++ b/src/config.c
@@ -743,6 +743,7 @@ int cgroup_config_load_config(const char *pathname)
        int namespace_enabled = 0;
        int mount_enabled = 0;
        yyin = fopen(pathname, "re");
+       int ret;
 
        if (!yyin) {
                cgroup_dbg("Failed to open file %s\n", pathname);
@@ -756,7 +757,16 @@ int cgroup_config_load_config(const char *pathname)
 
        init_cgroup_table(config_cgroup_table, MAX_CGROUPS);
 
-       if (yyparse() != 0) {
+       /*
+        * Parser calls longjmp() on really fatal error (like out-of-memory).
+        */
+       ret = setjmp(parser_error_env);
+       if (!ret)
+               ret = yyparse();
+       if (ret) {
+               /*
+                * Either yyparse failed or longjmp() was called.
+                */
                cgroup_dbg("Failed to parse file %s\n", pathname);
                fclose(yyin);
                free(config_cgroup_table);
diff --git a/src/lex.l b/src/lex.l
index 8a99bbc..7a00015 100644
--- a/src/lex.l
+++ b/src/lex.l
@@ -17,8 +17,13 @@
 #include <libcgroup-internal.h>
 #include "parse.h"
 int line_no = 1;
+jmp_buf parser_error_env;
 
-#define YY_FATAL_ERROR(msg) fprintf(stderr, "%s\n", msg)
+#define YY_FATAL_ERROR(msg) \
+       do { \
+               fprintf(stderr, "%s\n", msg); \
+               longjmp(parser_error_env, 1); \
+       } while(0);
 %}
 
 %option nounput noinput
diff --git a/src/libcgroup-internal.h b/src/libcgroup-internal.h
index de437e1..7d683f4 100644
--- a/src/libcgroup-internal.h
+++ b/src/libcgroup-internal.h
@@ -25,6 +25,7 @@ __BEGIN_DECLS
 #include <pthread.h>
 #include <sys/stat.h>
 #include <sys/types.h>
+#include <setjmp.h>
 
 /* Maximum number of mount points/controllers */
 #define MAX_MNT_ELEMENTS       8
@@ -185,6 +186,11 @@ struct cgroup_dictionary_iterator {
  */
 extern __thread int last_errno;
 
+/**
+ * 'Exception handler' for lex parser.
+ */
+extern jmp_buf parser_error_env;
+
 /* Internal API */
 char *cg_build_path(const char *name, char *path, const char *type);
 int cgroup_get_uid_gid_from_procfs(pid_t pid, uid_t *euid, gid_t *egid);


------------------------------------------------------------------------------
uberSVN's rich system and user administration capabilities and model 
configuration take the hassle out of deploying and managing Subversion and 
the tools developers use with it. Learn more about uberSVN and get a free 
download at:  http://p.sf.net/sfu/wandisco-dev2dev
_______________________________________________
Libcg-devel mailing list
Libcg-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/libcg-devel

Reply via email to