RPM Package Manager, CVS Repository
/cvs/
____________________________________________________________________________
Server: rpm5.org Name: Eric Veith
Root: /v/rpm/cvs Email: eveith@rpm5.org
Module: rpm Date: 18-Sep-2010 18:37:06
Branch: HEAD Handle: 2010091816370600
Modified files:
rpm/rpmio rpmruby.c rpmruby.h
Log:
Prevented embedded Ruby interpreter from being initialized twice
Summary:
Revision Changes Path
2.16 +101 -71 rpm/rpmio/rpmruby.c
2.9 +110 -53 rpm/rpmio/rpmruby.h
____________________________________________________________________________
patch -p0 <<'@@ .'
Index: rpm/rpmio/rpmruby.c
============================================================================
$ cvs diff -u -r2.15 -r2.16 rpmruby.c
--- rpm/rpmio/rpmruby.c 16 Aug 2010 13:17:41 -0000 2.15
+++ rpm/rpmio/rpmruby.c 18 Sep 2010 16:37:06 -0000 2.16
@@ -1,28 +1,28 @@
#include "system.h"
#include <argv.h>
-/* XXX grrr, ruby.h includes its own config.h too. */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
-#undef PACKAGE_NAME
-#undef PACKAGE_TARNAME
-#undef PACKAGE_VERSION
-#undef PACKAGE_STRING
-#undef PACKAGE_BUGREPORT
+
#if defined(WITH_RUBYEMBED)
+
+/* Make sure Ruby's fun stuff has its own xmalloc & Co functions available */
+
+#undef xmalloc
+#undef xcalloc
+#undef xrealloc
+
#include <ruby.h>
-#if !defined(RSTRING_PTR)
-/* XXX retrofit for ruby-1.8.5 in CentOS5 */
-#define RSTRING_PTR(s) (RSTRING(s)->ptr)
-#define RSTRING_LEN(s) (RSTRING(s)->len)
#endif
-#endif
-#define _RPMRUBY_INTERNAL
+/**
+ * Allows access to the gory details of rpmruby pool items.
+ */
+#define _RPMRUBY_INTERNAL 1
#include "rpmruby.h"
#include "debug.h"
@@ -33,22 +33,42 @@
/*@unchecked@*/ /*@relnull@*/
rpmruby _rpmrubyI = NULL;
-static void rpmrubyFini(void * _ruby)
+
+
+/**
+ * Finalizes a Ruby interpreter instance/pool item
+ */
+static void rpmrubyFini(void *_ruby)
/*@globals fileSystem @*/
/*@modifies *_ruby, fileSystem @*/
{
rpmruby ruby = _ruby;
-#if defined(WITH_RUBYEMBED)
- ruby_finalize();
- ruby_cleanup(0);
-#endif
+# if defined(WITH_RUBYEMBED)
+ ruby_cleanup(0);
+# endif
ruby->I = NULL;
}
+
+/**
+* The pool of Ruby interpreter instances
+* @see rpmioPool
+*/
/*@unchecked@*/ /*@only@*/ /*@null@*/
rpmioPool _rpmrubyPool;
+
+/**
+ * Returns the current rpmio pool responsible for Ruby interpreter instances
+ *
+ * This is a wrapper function that returns the current rpmio pool responsible
+ * for embedded Ruby interpreters. It creates and initializes a new pool when
+ * there is no current pool.
+ *
+ * @return The current pool
+ * @see rpmioNewPool
+ */
static rpmruby rpmrubyGetPool(/*@null@*/ rpmioPool pool)
/*@globals _rpmrubyPool, fileSystem @*/
/*@modifies pool, _rpmrubyPool, fileSystem @*/
@@ -57,90 +77,100 @@
if (_rpmrubyPool == NULL) {
_rpmrubyPool = rpmioNewPool("ruby", sizeof(*ruby), -1, _rpmruby_debug,
- NULL, NULL, rpmrubyFini);
+ NULL, NULL, rpmrubyFini);
pool = _rpmrubyPool;
- }
+ }
+
return (rpmruby) rpmioGetPool(pool, sizeof(*ruby));
}
+
/*@unchecked@*/
#if defined(WITH_RUBYEMBED)
+
+/** Initializes Ruby's StringIO for storing output in a string. */
static const char * rpmrubyInitStringIO = "\
require 'stringio'\n\
$stdout = StringIO.new($result, \"w+\")\n\
";
+
#endif
-static rpmruby rpmrubyI(void)
- /*@globals _rpmrubyI @*/
- /*@modifies _rpmrubyI @*/
+
+static rpmruby rpmrubyI()
+ /*@globals _rpmrubyI @*/
+ /*@modifies _rpmrubyI @*/
{
- if (_rpmrubyI == NULL)
- _rpmrubyI = rpmrubyNew(NULL, 0);
+ if (NULL == _rpmrubyI) {
+ _rpmrubyI = rpmrubyNew(NULL, 0);
+ }
return _rpmrubyI;
}
-rpmruby rpmrubyNew(char ** av, uint32_t flags)
-{
- rpmruby ruby =
-#ifdef NOTYET
- (flags & 0x80000000) ? rpmrubyI() :
-#endif
- rpmrubyGetPool(_rpmrubyPool);
-
- static char * _av[] = { "rpmruby", NULL };
- if (av == NULL) av = _av;
+rpmruby rpmrubyNew(char **av, uint32_t flags)
+{
+ /* TODO: Once Ruby allows several interpreter instances, distinguish
+ * between the global interpreter (1<<31 flag) and a new one.
+ */
+
+ if (NULL != _rpmrubyI) {
+ return _rpmrubyI;
+ }
-#if defined(WITH_RUBYEMBED)
- ruby_init();
- ruby_init_loadpath();
- ruby_script((char *)av[0]);
- ruby_set_argv(argvCount((ARGV_t)av)-1, av+1);
- rb_gv_set("$result", rb_str_new2(""));
- (void) rpmrubyRun(ruby, rpmrubyInitStringIO, NULL);
-#endif
+ rpmruby ruby = rpmrubyGetPool(_rpmrubyPool);
- return rpmrubyLink(ruby);
-}
+ static char *_av[] = { "rpmruby", NULL };
+ if (NULL == av) {
+ av = _av;
+ }
-rpmRC rpmrubyRunFile(rpmruby ruby, const char * fn, const char ** resultp)
-{
- rpmRC rc = RPMRC_FAIL;
-if (_rpmruby_debug)
-fprintf(stderr, "==> %s(%p,%s)\n", __FUNCTION__, ruby, fn);
+ /* Set up embedded Ruby interpreter if embedded Ruby is enabled. */
- if (ruby == NULL) ruby = rpmrubyI();
+# if defined(WITH_RUBYEMBED)
+ RUBY_INIT_STACK;
+ ruby_init();
+ ruby_init_loadpath();
+
+ ruby_script((char *)av[0]);
+ rb_gv_set("$result", rb_str_new2(""));
+ (void) rpmrubyRun(ruby, rpmrubyInitStringIO, NULL);
+# endif
- if (fn != NULL) {
-#if defined(WITH_RUBYEMBED)
- rb_load_file(fn);
- ruby->state = ruby_exec();
- if (resultp != NULL)
- *resultp = RSTRING_PTR(rb_gv_get("$result"));
- rc = RPMRC_OK;
-#endif
- }
- return rc;
+ return rpmrubyLink(ruby);
}
-rpmRC rpmrubyRun(rpmruby ruby, const char * str, const char ** resultp)
+
+rpmRC rpmrubyRun(rpmruby ruby, const char *str, const char **resultp)
{
rpmRC rc = RPMRC_FAIL;
-if (_rpmruby_debug)
-fprintf(stderr, "==> %s(%p,%s,%p)\n", __FUNCTION__, ruby, str, resultp);
+ if (_rpmruby_debug) {
+ fprintf(stderr, "==> %s(%p,%s,%p)\n",
+ __FUNCTION__, ruby, str, resultp);
+ }
- if (ruby == NULL) ruby = rpmrubyI();
+ if (NULL == ruby) {
+ ruby = rpmrubyI();
+ }
- if (str != NULL) {
-#if defined(WITH_RUBYEMBED)
- ruby->state = rb_eval_string(str);
- if (resultp != NULL)
- *resultp = RSTRING_PTR(rb_gv_get("$result"));
- rc = RPMRC_OK;
-#endif
+ if (NULL != str) {
+# if defined(WITH_RUBYEMBED)
+ int state = -1;
+ ruby->state = rb_eval_string_protect(str, &state);
+
+ /* Check whether the evaluation was successful or not */
+
+ if(0 == state) {
+ rc = RPMRC_OK;
+ if (resultp != NULL) {
+ *resultp = RSTRING_PTR(rb_gv_get("$result"));
+ }
+ }
+# endif
}
+
return rc;
}
+
@@ .
patch -p0 <<'@@ .'
Index: rpm/rpmio/rpmruby.h
============================================================================
$ cvs diff -u -r2.8 -r2.9 rpmruby.h
--- rpm/rpmio/rpmruby.h 7 Apr 2010 03:20:06 -0000 2.8
+++ rpm/rpmio/rpmruby.h 18 Sep 2010 16:37:06 -0000 2.9
@@ -1,108 +1,165 @@
#ifndef RPMRUBY_H
#define RPMRUBY_H
-/** \ingroup rpmio
+
+/**
* \file rpmio/rpmruby.h
+ * \ingroup rpmio
+ *
+ * Embedded Ruby interpreter
+ *
+ * This allows the embedding of the Ruby interpreter into RPM5. It can be
+ * used, for example, for expanding in the fashion of
+ * <tt>%%expand{ruby ...}</tt>.
+ *
+ * Currently (as of ruby-1.9.2), the Ruby interpreter allows only one instance
+ * of itself per process. As such, rpmio's pooling mechanism will also always
+ * contain only one ::rpmruby instance. Calling rpmrubyNew() will initialize
+ * a new interpreter, while rpmrubyFree() beds this instance. Make sure you
+ * keep things in order, that is, call rpmrubyNew() exactly once, and don't
+ * forget to call rpmrubyFree() when you're done. Repeatedly calling
+ * rpmrubyNew will have no effect while an interpreter is allocated.
+ *
+ * You can use rpmrubyRun() to evaluate Ruby code and get the result back.
*/
+
#include <rpmiotypes.h>
#include <rpmio.h>
-typedef /*@abstract@*/ /*@refcounted@*/ struct rpmruby_s * rpmruby;
+/** Triggers printing of debugging information */
/*@unchecked@*/
extern int _rpmruby_debug;
+typedef /*@abstract@*/ /*@refcounted@*/ struct rpmruby_s* rpmruby;
+
+/**
+ * Current (global) interpreter instance
+ *
+ * At the moment, this variable is merely a safeguard against initializing the
+ * Ruby interpreter over and over again. In the future, when there is Ruby
+ * support for multiple interpreter instances, a flag given to rpmrubyNew()
+ * will use this variable and return the global interpreter instance.
+ */
/*@unchecked@*/ /*@relnull@*/
extern rpmruby _rpmrubyI;
+
#if defined(_RPMRUBY_INTERNAL)
+
+/**
+ * Instances of this struct carry an embedded Ruby interpreter and the state
+ * associated with it.
+ */
struct rpmruby_s {
- struct rpmioItem_s _item; /*!< usage mutex and pool identifier. */
- void * I;
+
+ /**
+ * Pool identifier, including usage mutex, etc.
+ * \see rpmioItem_s
+ */
+ struct rpmioItem_s _item;
+
+ /** The actual interpreter instance */
+ void *I;
+
+ /**
+ * Carries the interpreter's current state, e.g. the latest return code.
+ * */
unsigned long state;
+
#if defined(__LCLINT__)
-/*@refs@*/
- int nrefs; /*!< (unused) keep splint happy */
+ /** Reference count: Currently unused, only to keep splint happy. */
+ /*@refs@*/
+ int nrefs;
#endif
};
+
#endif /* _RPMRUBY_INTERNAL */
+
#ifdef __cplusplus
extern "C" {
#endif
+
/**
- * Unreference a ruby interpreter instance.
- * @param ruby ruby interpreter
- * @return NULL on last dereference
+ * Dereferences a Ruby interpreter instance in the rpmio pool
+ *
+ * @param ruby Ruby interpreter pool item
+ * @return NULL on last dereference
+ * @see rpmUnlinkPoolItem
*/
/*@unused@*/ /*@null@*/
rpmruby rpmrubyUnlink (/*@killref@*/ /*@only@*/ /*@null@*/ rpmruby ruby)
- /*@modifies ruby @*/;
-#define rpmrubyUnlink(_ruby) \
- ((rpmruby)rpmioUnlinkPoolItem((rpmioItem)(_ruby), __FUNCTION__, __FILE__, __LINE__))
+ /*@modifies ruby @*/;
+#define rpmrubyUnlink(_ruby) \
+ ((rpmruby)rpmioUnlinkPoolItem((rpmioItem)(_ruby), __FUNCTION__, \
+ __FILE__, __LINE__))
+
/**
- * Reference a ruby interpreter instance.
- * @param ruby ruby interpreter
- * @return new ruby interpreter reference
+ * References a Ruby interpreter instance in the rpmio pool
+ *
+ * @param ruby Ruby interpreter
+ * @return A new ruby interpreter reference
+ * @see rpmioLinkPoolItem
*/
/*@unused@*/ /*@newref@*/ /*@null@*/
rpmruby rpmrubyLink (/*@null@*/ rpmruby ruby)
/*@modifies ruby @*/;
-#define rpmrubyLink(_ruby) \
- ((rpmruby)rpmioLinkPoolItem((rpmioItem)(_ruby), __FUNCTION__, __FILE__, __LINE__))
+#define rpmrubyLink(_ruby) \
+ ((rpmruby)rpmioLinkPoolItem((rpmioItem)(_ruby), __FUNCTION__, \
+ __FILE__, __LINE__))
+
/**
- * Destroy a ruby interpreter.
- * @param ruby ruby interpreter
- * @return NULL on last dereference
+ * Destroys a Ruby interpreter instance in the rpmio pool
+ *
+ * @param ruby The Ruby interpreter to be destroyed
+ * @return NULL on last dereference
+ * @see rpmioFreePoolItem
*/
/*@null@*/
-rpmruby rpmrubyFree(/*@killref@*/ /*@null@*/rpmruby ruby)
+rpmruby rpmrubyFree(/*@killref@*/ /*@null@*/ rpmruby ruby)
/*@globals fileSystem @*/
/*@modifies ruby, fileSystem @*/;
#define rpmrubyFree(_ruby) \
- ((rpmruby)rpmioFreePoolItem((rpmioItem)(_ruby), __FUNCTION__, __FILE__, __LINE__))
+ ((rpmruby)rpmioFreePoolItem((rpmioItem)(_ruby), __FUNCTION__, \
+ __FILE__, __LINE__))
+
/**
- * Create and load a ruby interpreter.
- * @param av ruby interpreter args (or NULL)
- * @param flags ruby interpreter flags ((1<<31): use global interpreter)
- * @return new ruby interpreter
+ * Creates and initializes a Ruby interpreter
+ *
+ * @param av Arguments to the Ruby interpreter (may be NULL)
+ * @param flags Ruby interpreter flags; ((1<<31): use global interpreter)
+ * @return A new Ruby interpreter
*/
/*@newref@*/ /*@null@*/
-rpmruby rpmrubyNew(/*@null@*/ char ** av, uint32_t flags)
- /*@globals fileSystem, internalState @*/
- /*@modifies fileSystem, internalState @*/;
-
-/**
- * Execute ruby from a file.
- * @param ruby ruby interpreter (NULL uses global interpreter)
- * @param fn ruby file to run (NULL returns RPMRC_FAIL)
- * @param *resultp ruby exec result
- * @return RPMRC_OK on success
- */
-rpmRC rpmrubyRunFile(rpmruby ruby, /*@null@*/ const char * fn,
- /*@null@*/ const char ** resultp)
- /*@globals fileSystem, internalState @*/
- /*@modifies ruby, fileSystem, internalState @*/;
-
-/**
- * Execute ruby string.
- * @param ruby ruby interpreter (NULL uses global interpreter)
- * @param str ruby string to execute (NULL returns RPMRC_FAIL)
- * @param *resultp ruby exec result
- * @return RPMRC_OK on success
- */
-rpmRC rpmrubyRun(rpmruby ruby, /*@null@*/ const char * str,
- /*@null@*/ const char ** resultp)
- /*@globals fileSystem, internalState @*/
- /*@modifies ruby, *resultp, fileSystem, internalState @*/;
+rpmruby rpmrubyNew(/*@null@*/ char **av, uint32_t flags)
+ /*@globals fileSystem, internalState @*/
+ /*@modifies fileSystem, internalState @*/;
+
+
+/**
+ * Evaluates Ruby code stored in a string
+ *
+ * @param ruby The Ruby interpreter that is to be used
+ * (NULL uses global interpreter)
+ * @param str Ruby code to evaluate (NULL forces return of RPMRC_FAIL)
+ * @param *resultp Result of the evaluation
+ * @return RPMRC_OK on success
+ */
+rpmRC rpmrubyRun(rpmruby ruby, /*@null@*/ const char *str,
+ /*@null@*/ const char **resultp)
+ /*@globals fileSystem, internalState @*/
+ /*@modifies ruby, *resultp, fileSystem, internalState @*/;
+
#ifdef __cplusplus
}
#endif
#endif /* RPMRUBY_H */
+
@@ .
Received on Sat Sep 18 18:37:06 2010