The primary_resreq action ignored parse_resreq_primary()'s result, so a primary whose select (or rusage) clause failed to parse was accepted without that clause: select[type==] or select[mem>] matched every host. A malformed clause now fails the whole resreq, and parse_resreq() returns the clause's own message. A select naming an unregistered resource is still dropped, not an error: parse_select() reports it as -ENOENT (new select_context_t .unknown_resource) and the action lets it pass, because jobs rely on it -- the scheduler's own "type == any" default among them when no "type" resource is registered (making it fatal failed 36 scheduler suites). Test: test_resreq_primary_select_error_fails_parse RED before (all accepted), GREEN after. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
133 lines
3.8 KiB
Text
133 lines
3.8 KiB
Text
%prefix "xce_resreq"
|
|
%value "char *"
|
|
%auxil "resreq_context_t *"
|
|
%source {
|
|
#include <errno.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#if 0
|
|
static const char *dbg_str[] = { "Evaluating rule", "Matched rule", "Abandoning rule" };
|
|
#define PCC_DEBUG(auxil, event, rule, level, pos, buffer, length) \
|
|
fprintf(stderr, "%*s%s %s @%zu [%.*s]\n", (int)((level) * 2), "", dbg_str[event], rule, pos, (int)(length), buffer)
|
|
#endif
|
|
#define PCC_ERROR(auxil) my_resreq_error(auxil)
|
|
|
|
static void my_resreq_error(resreq_context_t *auxil) {
|
|
/* Calculate line/column from max_err */
|
|
auxil->has_error = 1;
|
|
}
|
|
}
|
|
|
|
%common {
|
|
#include "resreq.h"
|
|
#include "xlist.h"
|
|
|
|
#define PCC_GETCHAR(auxil) \
|
|
({ int c = (auxil->input[auxil->pos] != '\0') ? (int)auxil->input[auxil->pos ++]: -1; \
|
|
if (auxil->pos > auxil->err_pos) auxil->err_pos = auxil->pos; \
|
|
c; \
|
|
})
|
|
|
|
}
|
|
|
|
statement <- _ resreq _ EOF
|
|
|
|
resreq <- alter_resreq {
|
|
xce_resreq_t *resreq = auxil->resreq;
|
|
resreq->tag = XCE_RESREQ_ALTER;
|
|
resreq->u.alter = auxil->alter;
|
|
auxil->alter = NULL;
|
|
}
|
|
/ compound_resreq {
|
|
xce_resreq_t *resreq = auxil->resreq;
|
|
if (resreq != NULL) {
|
|
resreq->tag = XCE_RESREQ_COMPOUND;
|
|
resreq->u.compound = auxil->compound;
|
|
auxil->compound = NULL;
|
|
}
|
|
}
|
|
/ primary_resreq {
|
|
xce_resreq_t *resreq = auxil->resreq;
|
|
if (resreq != NULL) {
|
|
resreq->tag = XCE_RESREQ_PRIMARY;
|
|
resreq->u.primary = auxil->primary;
|
|
auxil->primary = NULL;
|
|
}
|
|
}
|
|
|
|
alter_resreq <- alter_resreq_term _ ('||' _ alter_resreq_term _)*
|
|
|
|
alter_resreq_term <- '{' _ compound_resreq _ '}' _ {
|
|
xce_alter_resreq_t *alter = auxil->alter;
|
|
if (alter == NULL) {
|
|
alter = (xce_alter_resreq_t *)calloc(1, sizeof(*alter));
|
|
if (alter != NULL) {
|
|
xlist_init(&(alter->compounds), 8);
|
|
}
|
|
|
|
auxil->alter = alter;
|
|
}
|
|
|
|
if (alter != NULL) {
|
|
if (auxil->compound != NULL) {
|
|
xlist_store(&(alter->compounds), auxil->compound);
|
|
auxil->compound = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
compound_resreq <- compound_resreq_term _ ('+' _ compound_resreq_term _)*
|
|
|
|
compound_resreq_term <- < int_num _ '*' _ '{' _ primary_resreq _ '}' _
|
|
/ '{' _ primary_resreq _ '}' _ > {
|
|
xce_compound_resreq_t *compound = auxil->compound;
|
|
if (compound == NULL) {
|
|
compound = (xce_compound_resreq_t *)calloc(1, sizeof(*compound));
|
|
if (compound != NULL) {
|
|
xlist_init(&(compound->primaries), 8);
|
|
}
|
|
auxil->compound = compound;
|
|
}
|
|
|
|
if (compound != NULL) {
|
|
xce_primary_resreq_t *primary = auxil->primary;
|
|
|
|
if (primary != NULL) {
|
|
primary->minTasks = auxil->resreq_fact_count;
|
|
primary->maxTasks = auxil->resreq_fact_count;
|
|
xlist_store(&(compound->primaries), primary);
|
|
auxil->primary = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
primary_resreq <- < (! ('{' / '}' ) .)* > {
|
|
xce_primary_resreq_t *primary = (xce_primary_resreq_t *)calloc(1, sizeof(*primary));
|
|
if (primary != NULL) {
|
|
auxil->primary = primary;
|
|
free(auxil->errmsg); /* bug-1884: an earlier primary's message */
|
|
auxil->errmsg = NULL;
|
|
/* bug-1887: a primary whose select/rusage is malformed fails the
|
|
* whole resreq (it was kept without that clause). A select naming
|
|
* an unregistered resource (-ENOENT) is still dropped, as before --
|
|
* jobs rely on it, the scheduler's own "type == any" default among
|
|
* them when no "type" resource is registered. */
|
|
{
|
|
int prc = parse_resreq_primary(primary, (char *)$0, auxil->resmgr,
|
|
&(auxil->errmsg));
|
|
if ((prc < 0) && (prc != -ENOENT)) {
|
|
auxil->has_error = 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
int_num <- < [0-9]+ > { auxil->resreq_fact_count = atoi($0); }
|
|
|
|
EOL <- "\n" / "\r\n" / "\r" / "\0"
|
|
|
|
_ <- [ \t]*
|
|
|
|
EOF <- !.
|