14 #include <sys/types.h> 
   39 static int operations = 0;
 
   40 static GHashTable *recurring_actions = NULL;
 
   44 static GList *blocked_ops = NULL;
 
   47 static GList *inflight_ops = NULL;
 
   49 static void handle_blocked_ops(
void);
 
   55                                    action, interval, timeout, NULL, 0);
 
   83     if (rc > 0 && stat(path, &st) == 0) {
 
  105 init_recurring_actions(
void)
 
  107     if (recurring_actions == NULL) {
 
  108         recurring_actions = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
 
  121 static inline gboolean
 
  126             && (g_list_find(inflight_ops, op) != NULL);
 
  142 expand_resource_class(
const char *rsc, 
const char *standard, 
const char *agent)
 
  144     char *expanded_class = NULL;
 
  150             crm_debug(
"Found %s agent %s for %s", found_class, agent, rsc);
 
  151             expanded_class = strdup(found_class);
 
  153             crm_info(
"Assuming resource class lsb for agent %s for %s",
 
  158         expanded_class = strdup(standard);
 
  161     return expanded_class;
 
  166                         const char *agent, 
const char *action, 
int interval, 
int timeout,
 
  176     if (crm_strlen_zero(name)) {
 
  177         crm_err(
"Cannot create operation without resource name");
 
  181     if (crm_strlen_zero(standard)) {
 
  182         crm_err(
"Cannot create operation for %s without resource class", name);
 
  187         crm_err(
"Cannot create OCF operation for %s without provider", name);
 
  191     if (crm_strlen_zero(agent)) {
 
  192         crm_err(
"Cannot create operation for %s without agent name", name);
 
  196     if (crm_strlen_zero(action)) {
 
  197         crm_err(
"Cannot create operation for %s without operation name", name);
 
  207     op->
rsc = strdup(name);
 
  210     op->
standard = expand_resource_class(name, standard, agent);
 
  211     op->
agent = strdup(agent);
 
  223     op->
action = strdup(action);
 
  231             crm_err(
"Internal error: cannot create agent path");
 
  238         if (op->
agent[0] == 
'/') {
 
  243             crm_err(
"Internal error: cannot create agent path");
 
  249 #if SUPPORT_HEARTBEAT 
  256         if (op->
agent[0] == 
'/') {
 
  260         } 
else if (asprintf(&op->
opaque->
exec, 
"%s/%s", HB_RA_DIR, op->
agent) == -1) {
 
  261             crm_err(
"Internal error: cannot create agent path");
 
  270             for (index = 1; index <= 
MAX_ARGC - 3; index++ ) {
 
  271                 snprintf(buf_tmp, 
sizeof(buf_tmp), 
"%d", index);
 
  272                 value_tmp = g_hash_table_lookup(params, buf_tmp);
 
  273                 if (value_tmp == NULL) {
 
  278                 op->
opaque->
args[param_num++] = strdup(value_tmp);
 
  299         if (op->
agent[0] == 
'/') {
 
  305             crm_err(
"Internal error: cannot create agent path");
 
  314             op->
opaque->
args[index] = strdup(
"--version");
 
  321             static int args_size = 
sizeof(op->
opaque->
args) / 
sizeof(
char *);
 
  323             g_hash_table_iter_init(&iter, params);
 
  325             while (g_hash_table_iter_next(&iter, (gpointer *) & key, (gpointer *) & value) &&
 
  326                    index <= args_size - 3) {
 
  328                 char *long_opt = NULL;
 
  335                 long_opt = calloc(1, len);
 
  336                 sprintf(long_opt, 
"--%s", key);
 
  337                 long_opt[len - 1] = 0;
 
  353         g_hash_table_destroy(params);
 
  359         g_hash_table_destroy(params);
 
  370     unsigned int cur_arg;
 
  372     op = calloc(1, 
sizeof(*op));
 
  378     for (cur_arg = 1; args && args[cur_arg - 1]; cur_arg++) {
 
  379         op->
opaque->
args[cur_arg] = strdup(args[cur_arg - 1]);
 
  382             crm_err(
"svc_action_t args list not long enough for '%s' execution request.", exec);
 
  406                       GHashTable *params, 
int sequence, 
void *cb_data)
 
  412     action->
id = strdup(
id);
 
  437     CRM_CHECK((op != NULL) && (user != NULL), 
return -EINVAL);
 
  442 set_alert_env(gpointer key, gpointer value, gpointer user_data)
 
  447         rc = 
setenv(key, value, 1);
 
  454                   (
char*)key, (value? (
char*)value : 
""));
 
  456         crm_trace(
"setenv %s=%s", (
char*)key, (value? (
char*)value : 
""));
 
  461 unset_alert_env(gpointer key, gpointer value, gpointer user_data)
 
  463     if (unsetenv(key) < 0) {
 
  484     gboolean responsible;
 
  489         g_hash_table_foreach(action->
params, set_alert_env, NULL);
 
  493         g_hash_table_foreach(action->
params, unset_alert_env, NULL);
 
  507 services_set_op_pending(
svc_action_t *op, DBusPendingCall *pending)
 
  509     if (op->
opaque->pending && (op->
opaque->pending != pending)) {
 
  515         dbus_pending_call_unref(op->
opaque->pending);
 
  517     op->
opaque->pending = pending;
 
  519         crm_trace(
"Updated pending %s DBus call (%p)", op->
id, pending);
 
  534     if(op->
opaque->timerid != 0) {
 
  536         g_source_remove(op->
opaque->timerid);
 
  542         if(dbus_pending_call_get_completed(op->
opaque->pending)) {
 
  545         dbus_pending_call_cancel(op->
opaque->pending);
 
  546         dbus_pending_call_unref(op->
opaque->pending);
 
  547         op->
opaque->pending = NULL;
 
  575     CRM_CHECK(g_list_find(inflight_ops, op) == NULL, 
return);
 
  576     CRM_CHECK(g_list_find(blocked_ops, op) == NULL, 
return);
 
  578               || (g_hash_table_lookup(recurring_actions, op->
id) == NULL),
 
  607         g_hash_table_destroy(op->
params);
 
  619     if (recurring_actions) {
 
  620         g_hash_table_remove(recurring_actions, op->
id);
 
  643     gboolean cancelled = FALSE;
 
  648     init_recurring_actions();
 
  649     op = g_hash_table_lookup(recurring_actions, 
id);
 
  667         crm_info(
"Terminating in-flight op %s (pid %d) early because it was cancelled",
 
  670         if (cancelled == FALSE) {
 
  671             crm_err(
"Termination of %s (pid %d) failed", 
id, op->
pid);
 
  681     if (inflight_systemd_or_upstart(op)) {
 
  682         crm_info(
"Will cancel %s op %s when in-flight instance completes",
 
  694     blocked_ops = g_list_remove(blocked_ops, op);
 
  709     init_recurring_actions();
 
  710     op = g_hash_table_lookup(recurring_actions, 
id);
 
  718     if (op->
pid || inflight_systemd_or_upstart(op)) {
 
  745     dup = g_hash_table_lookup(recurring_actions, op->
id);
 
  747     if (dup && (dup != op)) {
 
  770 inline static gboolean
 
  805         inflight_ops = g_list_append(inflight_ops, op);
 
  819     inflight_ops = g_list_remove(inflight_ops, op);
 
  820     blocked_ops = g_list_remove(blocked_ops, op);
 
  823     handle_blocked_ops();
 
  830     if (action_callback) {
 
  835         init_recurring_actions();
 
  836         if (handle_duplicate_recurring(op) == TRUE) {
 
  841         g_hash_table_replace(recurring_actions, op->
id, op);
 
  845         blocked_ops = g_list_append(blocked_ops, op);
 
  849     return action_exec_helper(op);
 
  853 static gboolean processing_blocked_ops = FALSE;
 
  861     for (gIter = inflight_ops; gIter != NULL; gIter = gIter->next) {
 
  872 handle_blocked_ops(
void)
 
  874     GList *executed_ops = NULL;
 
  877     gboolean res = FALSE;
 
  879     if (processing_blocked_ops) {
 
  884     processing_blocked_ops = TRUE;
 
  888     for (gIter = blocked_ops; gIter != NULL; gIter = gIter->next) {
 
  893         executed_ops = g_list_append(executed_ops, op);
 
  894         res = action_exec_helper(op);
 
  903     for (gIter = executed_ops; gIter != NULL; gIter = gIter->next) {
 
  905         blocked_ops = g_list_remove(blocked_ops, op);
 
  907     g_list_free(executed_ops);
 
  909     processing_blocked_ops = FALSE;
 
  912 #define lsb_metadata_template  \ 
  913     "<?xml version='1.0'?>\n"                                           \ 
  914     "<!DOCTYPE resource-agent SYSTEM 'ra-api-1.dtd'>\n"                 \ 
  915     "<resource-agent name='%s' version='" PCMK_DEFAULT_AGENT_VERSION "'>\n" \ 
  916     "  <version>1.0</version>\n"                                        \ 
  917     "  <longdesc lang='en'>\n"                                          \ 
  920     "  <shortdesc lang='en'>%s</shortdesc>\n"                           \ 
  924     "    <action name='meta-data'    timeout='5' />\n"                  \ 
  925     "    <action name='start'        timeout='15' />\n"                 \ 
  926     "    <action name='stop'         timeout='15' />\n"                 \ 
  927     "    <action name='status'       timeout='15' />\n"                 \ 
  928     "    <action name='restart'      timeout='15' />\n"                 \ 
  929     "    <action name='force-reload' timeout='15' />\n"                 \ 
  930     "    <action name='monitor'      timeout='15' interval='15' />\n"   \ 
  932     "  <special tag='LSB'>\n"                                           \ 
  933     "    <Provides>%s</Provides>\n"                                     \ 
  934     "    <Required-Start>%s</Required-Start>\n"                         \ 
  935     "    <Required-Stop>%s</Required-Stop>\n"                           \ 
  936     "    <Should-Start>%s</Should-Start>\n"                             \ 
  937     "    <Should-Stop>%s</Should-Stop>\n"                               \ 
  938     "    <Default-Start>%s</Default-Start>\n"                           \ 
  939     "    <Default-Stop>%s</Default-Stop>\n"                             \ 
  941     "</resource-agent>\n" 
  946 #define LSB_INITSCRIPT_INFOBEGIN_TAG "### BEGIN INIT INFO" 
  947 #define LSB_INITSCRIPT_INFOEND_TAG "### END INIT INFO" 
  948 #define PROVIDES    "# Provides:" 
  949 #define REQ_START   "# Required-Start:" 
  950 #define REQ_STOP    "# Required-Stop:" 
  951 #define SHLD_START  "# Should-Start:" 
  952 #define SHLD_STOP   "# Should-Stop:" 
  953 #define DFLT_START  "# Default-Start:" 
  954 #define DFLT_STOP   "# Default-Stop:" 
  955 #define SHORT_DSCR  "# Short-Description:" 
  956 #define DESCRIPTION "# Description:" 
  958 #define lsb_meta_helper_free_value(m)           \ 
  976 static inline gboolean
 
  977 lsb_meta_helper_get_value(
const char *line, 
char **value, 
const char *prefix)
 
  980         *value = (
char *)xmlEncodeEntitiesReentrant(NULL, BAD_CAST line+strlen(prefix));
 
  986 #define DESC_MAX 2048 
  989 lsb_get_metadata(
const char *
type, 
char **output)
 
  991     char ra_pathname[PATH_MAX] = { 0, };
 
  993     char buffer[1024] = { 0, };
 
  994     char *provides = NULL;
 
  995     char *req_start = NULL;
 
  996     char *req_stop = NULL;
 
  997     char *shld_start = NULL;
 
  998     char *shld_stop = NULL;
 
  999     char *dflt_start = NULL;
 
 1000     char *dflt_stop = NULL;
 
 1001     char *s_dscrpt = NULL;
 
 1002     char *xml_l_dscrpt = NULL;
 
 1004     bool in_header = FALSE;
 
 1005     char description[
DESC_MAX] = { 0, };
 
 1007     if (type[0] == 
'/') {
 
 1008         snprintf(ra_pathname, 
sizeof(ra_pathname), 
"%s", type);
 
 1010         snprintf(ra_pathname, 
sizeof(ra_pathname), 
"%s/%s",
 
 1014     crm_trace(
"Looking into %s", ra_pathname);
 
 1015     fp = fopen(ra_pathname, 
"r");
 
 1021     while (fgets(buffer, 
sizeof(buffer), fp)) {
 
 1033         if (lsb_meta_helper_get_value(buffer, &provides, 
PROVIDES)) {
 
 1036         if (lsb_meta_helper_get_value(buffer, &req_start, 
REQ_START)) {
 
 1039         if (lsb_meta_helper_get_value(buffer, &req_stop, 
REQ_STOP)) {
 
 1042         if (lsb_meta_helper_get_value(buffer, &shld_start, 
SHLD_START)) {
 
 1045         if (lsb_meta_helper_get_value(buffer, &shld_stop, 
SHLD_STOP)) {
 
 1048         if (lsb_meta_helper_get_value(buffer, &dflt_start, 
DFLT_START)) {
 
 1051         if (lsb_meta_helper_get_value(buffer, &dflt_stop, 
DFLT_STOP)) {
 
 1054         if (lsb_meta_helper_get_value(buffer, &s_dscrpt, 
SHORT_DSCR)) {
 
 1061             bool processed_line = TRUE;
 
 1064             offset += snprintf(description, 
DESC_MAX, 
"%s",
 
 1069             while (fgets(buffer, 
sizeof(buffer), fp)) {
 
 1075                     offset += snprintf(description + offset, 
DESC_MAX - offset,
 
 1081                     processed_line = FALSE;
 
 1087             xml_l_dscrpt = (
char *)xmlEncodeEntitiesReentrant(NULL, BAD_CAST(description));
 
 1089             if (processed_line) {
 
 1099         if (buffer[0] != 
'#') {
 
 1106                                 (xml_l_dscrpt? xml_l_dscrpt : type),
 
 1107                                 (s_dscrpt? s_dscrpt : type),
 
 1108                                 (provides? provides : 
""),
 
 1109                                 (req_start? req_start : 
""),
 
 1110                                 (req_stop? req_stop : 
""),
 
 1111                                 (shld_start? shld_start : 
""),
 
 1112                                 (shld_stop? shld_stop : 
""),
 
 1113                                 (dflt_start? dflt_start : 
""),
 
 1114                                 (dflt_stop? dflt_stop : 
""));
 
 1126     crm_trace(
"Created fake metadata: %llu",
 
 1127               (
unsigned long long) strlen(*output));
 
 1133 nagios_get_metadata(
const char *
type, 
char **output)
 
 1136     FILE *file_strm = NULL;
 
 1137     int start = 0, length = 0, read_len = 0;
 
 1141     file_strm = fopen(metadata_file, 
"r");
 
 1142     if (file_strm == NULL) {
 
 1143         crm_err(
"Metadata file %s does not exist", metadata_file);
 
 1144         free(metadata_file);
 
 1149     start = ftell(file_strm);
 
 1150     fseek(file_strm, 0L, SEEK_END);
 
 1151     length = ftell(file_strm);
 
 1152     fseek(file_strm, 0L, start);
 
 1158         crm_info(
"%s was not valid", metadata_file);
 
 1164         crm_trace(
"Reading %d bytes from file", length);
 
 1165         *output = calloc(1, (length + 1));
 
 1166         read_len = fread(*output, 1, length, file_strm);
 
 1167         if (read_len != length) {
 
 1168             crm_err(
"Calculated and read bytes differ: %d vs. %d",
 
 1177     free(metadata_file);
 
 1182 #if SUPPORT_HEARTBEAT 
 1198 static const char hb_metadata_template[] =
 
 1199     "<?xml version='1.0'?>\n" 
 1200     "<!DOCTYPE resource-agent SYSTEM 'ra-api-1.dtd'>\n" 
 1202     "<version>1.0</version>\n" 
 1203     "<longdesc lang='en'>\n" 
 1206     "<shortdesc lang='en'>%s</shortdesc>\n" 
 1208     "<parameter name='1' unique='1' required='0'>\n" 
 1209     "<longdesc lang='en'>\n" 
 1210     "This argument will be passed as the first argument to the " 
 1211     "heartbeat resource agent (assuming it supports one)\n" 
 1213     "<shortdesc lang='en'>argv[1]</shortdesc>\n" 
 1214     "<content type='string' default=' ' />\n" 
 1216     "<parameter name='2' unique='1' required='0'>\n" 
 1217     "<longdesc lang='en'>\n" 
 1218     "This argument will be passed as the second argument to the " 
 1219     "heartbeat resource agent (assuming it supports one)\n" 
 1221     "<shortdesc lang='en'>argv[2]</shortdesc>\n" 
 1222     "<content type='string' default=' ' />\n" 
 1224     "<parameter name='3' unique='1' required='0'>\n" 
 1225     "<longdesc lang='en'>\n" 
 1226     "This argument will be passed as the third argument to the " 
 1227     "heartbeat resource agent (assuming it supports one)\n" 
 1229     "<shortdesc lang='en'>argv[3]</shortdesc>\n" 
 1230     "<content type='string' default=' ' />\n" 
 1232     "<parameter name='4' unique='1' required='0'>\n" 
 1233     "<longdesc lang='en'>\n" 
 1234     "This argument will be passed as the fourth argument to the " 
 1235     "heartbeat resource agent (assuming it supports one)\n" 
 1237     "<shortdesc lang='en'>argv[4]</shortdesc>\n" 
 1238     "<content type='string' default=' ' />\n" 
 1240     "<parameter name='5' unique='1' required='0'>\n" 
 1241     "<longdesc lang='en'>\n" 
 1242     "This argument will be passed as the fifth argument to the " 
 1243     "heartbeat resource agent (assuming it supports one)\n" 
 1245     "<shortdesc lang='en'>argv[5]</shortdesc>\n" 
 1246     "<content type='string' default=' ' />\n" 
 1250     "<action name='start'   timeout='15' />\n" 
 1251     "<action name='stop'    timeout='15' />\n" 
 1252     "<action name='status'  timeout='15' />\n" 
 1253     "<action name='monitor' timeout='15' interval='15' start-delay='15' />\n" 
 1254     "<action name='meta-data'  timeout='5' />\n" 
 1256     "<special tag='heartbeat'>\n" 
 1258     "</resource-agent>\n";
 
 1261 heartbeat_get_metadata(
const char *type, 
char **output)
 
 1264     crm_trace(
"Created fake metadata: %llu",
 
 1265               (
unsigned long long) strlen(*output));
 
 1273     const char *
class = op->standard;
 
 1275     if (op->
agent == NULL) {
 
 1276         crm_err(
"meta-data requested without specifying agent");
 
 1280     if (
class == NULL) {
 
 1281         crm_err(
"meta-data requested for agent %s without specifying class",
 
 1290     if (
class == NULL) {
 
 1291         crm_err(
"meta-data requested for %s, but could not determine class",
 
 1306 #if SUPPORT_HEARTBEAT 
 1312     return action_exec_helper(op);
 
 1335         rc = action_get_metadata(op);
 
 1337         rc = action_exec_helper(op);
 
 1362 #if SUPPORT_HEARTBEAT 
 1364 resources_os_list_hb_agents(
void)
 
 1373     GList *standards = NULL;
 
 1374     GList *agents = NULL;
 
 1383         standards = g_list_append(standards,
 
 1385         g_list_free_full(agents, free);
 
 1392         standards = g_list_append(standards,
 
 1394         g_list_free_full(agents, free);
 
 1401         standards = g_list_append(standards,
 
 1403         g_list_free_full(agents, free);
 
 1407 #if SUPPORT_HEARTBEAT 
 1427     if ((standard == NULL)
 
 1434         if (standard == NULL) {
 
 1438                 result = g_list_concat(tmp1, tmp2);
 
 1445             result = g_list_concat(tmp1, tmp2);
 
 1453             result = g_list_concat(tmp1, tmp2);
 
 1463 #if SUPPORT_HEARTBEAT 
 1465         return resources_os_list_hb_agents();
 
#define CRM_CHECK(expr, failure_action)
 
#define lsb_metadata_template
 
void services_action_free(svc_action_t *op)
 
gboolean upstart_job_exists(const char *name)
 
svc_action_t * services_action_create(const char *name, const char *action, int interval, int timeout)
 
gboolean mainloop_child_kill(pid_t pid)
 
mainloop_io_t * stderr_gsource
 
const char * resources_find_service_class(const char *agent)
Find first service class that can provide a specified agent. 
 
GList * resources_os_list_ocf_agents(const char *provider)
 
GList * resources_os_list_ocf_providers(void)
 
#define PCMK_RESOURCE_CLASS_SYSTEMD
 
svc_action_t * resources_action_create(const char *name, const char *standard, const char *provider, const char *agent, const char *action, int interval, int timeout, GHashTable *params, enum svc_action_flags flags)
Create a new resource action. 
 
gboolean recurring_action_timer(gpointer data)
 
svc_action_t * services_action_create_generic(const char *exec, const char *args[])
 
GList * services_os_get_directory_list(const char *root, gboolean files, gboolean executable)
 
int crm_user_lookup(const char *name, uid_t *uid, gid_t *gid)
 
gboolean services_os_action_execute(svc_action_t *op)
 
G_GNUC_INTERNAL GList * resources_os_list_nagios_agents(void)
 
gboolean upstart_job_exec(svc_action_t *op)
 
gboolean is_op_blocked(const char *rsc)
 
Wrappers for and extensions to glib mainloop. 
 
bool crm_starts_with(const char *str, const char *prefix)
Check whether a string starts with a certain sequence. 
 
GList * resources_os_list_lsb_agents(void)
 
void services_action_cleanup(svc_action_t *op)
 
enum svc_action_flags flags
 
#define crm_warn(fmt, args...)
 
#define PCMK_RESOURCE_CLASS_OCF
 
gboolean cancel_recurring_action(svc_action_t *op)
 
svc_action_private_t * opaque
 
GList * upstart_job_listall(void)
 
#define crm_debug(fmt, args...)
 
svc_action_t * services_alert_create(const char *id, const char *exec, int timeout, GHashTable *params, int sequence, void *cb_data)
Create an alert agent action. 
 
gboolean operation_finalize(svc_action_t *op)
 
gboolean services_action_sync(svc_action_t *op)
 
gboolean systemd_unit_exists(const char *name)
 
#define PCMK_RESOURCE_CLASS_SERVICE
 
#define LSB_INITSCRIPT_INFOEND_TAG
 
#define crm_trace(fmt, args...)
 
int setenv(const char *name, const char *value, int why)
 
gboolean services_action_cancel(const char *name, const char *action, int interval)
Cancel a recurring action. 
 
void(* callback)(svc_action_t *op)
 
GList * resources_list_providers(const char *standard)
Get a list of providers. 
 
#define LSB_INITSCRIPT_INFOBEGIN_TAG
 
#define SUPPORT_HEARTBEAT
 
GList * systemd_unit_listall(void)
 
int services_action_user(svc_action_t *op, const char *user)
Set the user and group that an action will execute as. 
 
gboolean services_action_kick(const char *name, const char *action, int interval)
 
void services_add_inflight_op(svc_action_t *op)
 
void services_untrack_op(svc_action_t *op)
 
#define PCMK_RESOURCE_CLASS_NAGIOS
 
#define PCMK_RESOURCE_CLASS_LSB
 
#define crm_perror(level, fmt, args...)
Log a system error message. 
 
#define NAGIOS_PLUGIN_DIR
 
GList * resources_list_standards(void)
 
#define crm_err(fmt, args...)
 
GList * get_directory_list(const char *root, gboolean files, gboolean executable)
Get a list of files or directories in a given path. 
 
#define PCMK_RESOURCE_CLASS_UPSTART
 
#define PCMK_RESOURCE_CLASS_HB
 
#define PCMK_DEFAULT_AGENT_VERSION
 
GList * resources_list_agents(const char *standard, const char *provider)
Get a list of resource agents. 
 
mainloop_io_t * stdout_gsource
 
#define XML_ATTR_CRM_VERSION
 
gboolean services_alert_async(svc_action_t *action, void(*cb)(svc_action_t *op))
Execute an alert agent action. 
 
void mainloop_del_fd(mainloop_io_t *client)
 
bool crm_provider_required(const char *standard)
Check whether a resource standard requires a provider to be specified. 
 
char * generate_op_key(const char *rsc_id, const char *op_type, int interval)
Generate an operation key. 
 
GList * services_list(void)
 
#define safe_str_eq(a, b)
 
char * crm_strdup_printf(char const *format,...) __attribute__((__format__(__printf__
 
gboolean services_action_async(svc_action_t *op, void(*action_callback)(svc_action_t *))
 
gboolean systemd_unit_exec(svc_action_t *op)
 
#define crm_info(fmt, args...)
 
#define NAGIOS_METADATA_DIR
 
enum crm_ais_msg_types type
 
#define lsb_meta_helper_free_value(m)