ad841d50 was a mistake. It was never agreed in #40 that Fort should
shotgun blast its own face on the first ENOMEM, and even if it was, the
idea is preposterous. Memory allocation failures are neither programming
errors nor an excuse to leave all the routers hanging.
While there's some truth to the notion that a Fort memory leak (which
has been exhausting memory over time) could be temporarily amended by
killing Fort (and letting the OS clean it up), the argument completely
misses the reality that memory allocation failures could happen
regardless of the existence of a memory leak.
A memory leak is a valid reason to throw away the results of a current
validation run (as long as the admin is warned), but an existing
validation result and the RTR server must remain afloat.
Also includes a pr_enomem() caller review.
rval = ber_decode(&s_codec_ctx, descriptor, result, buffer,
buffer_size);
if (rval.code != RC_OK) {
- if (rval.code == RC_FAIL && errno == ENOMEM)
- pr_enomem();
-
/* Must free partial object according to API contracts. */
ASN_STRUCT_FREE(*descriptor, *result);
/* We expect the data to be complete; RC_WMORE is an error. */
error);
}
-void
-close_thread(pthread_t thread, char const *what)
-{
- int error;
-
- error = pthread_cancel(thread);
- if (error && error != ESRCH)
- pr_crit("pthread_cancel() threw %d on the '%s' thread.",
- error, what);
-
- error = pthread_join(thread, NULL);
- if (error)
- pr_crit("pthread_join() threw %d on the '%s' thread.",
- error, what);
-}
-
static int
process_file(char const *dir_name, char const *file_name, char const *file_ext,
int *fcount, process_file_cb cb, void *arg)
void rwlock_write_lock(pthread_rwlock_t *);
void rwlock_unlock(pthread_rwlock_t *);
-/** Also boilerplate. */
-void close_thread(pthread_t thread, char const *);
-
typedef int (*process_file_cb)(char const *, void *);
int process_file_or_dir(char const *, char const *, bool, process_file_cb,
void *);
error = string_array_init(&rpki_config.server.address, NULL, 0);
if (error)
- return pr_enomem();
+ return error;
rpki_config.server.port = strdup("323");
if (rpki_config.server.port == NULL) {
int
pr_enomem(void)
{
- /* TODO this being a critical is not acceptable */
- pr_crit("Out of memory.");
+ /*
+ * I'm not using PR_SIMPLE and friends, because those allocate.
+ * We want to minimize allocations after a memory allocation failure.
+ */
+
+ if (LOG_ERR > op_config.level)
+ return -ENOMEM;
+
+ if (op_config.syslog_enabled) {
+ lock_mutex();
+ syslog(LOG_ERR | op_config.facility, "Out of memory.");
+ unlock_mutex();
+ }
+
+ if (op_config.fprintf_enabled) {
+ lock_mutex();
+ fprintf(stderr, "Out of memory.\n");
+ unlock_mutex();
+ }
+
+ return -ENOMEM;
}
__dead void
{
int error;
- printf("Fort 1.5.0.1\n");
/* Initializations */
error = log_setup();
if (error)
- return error;
+ goto just_quit;
+
+ /* TODO (issue49) don't forget to improve this. */
+ pr_op_info("Fort 1.5.0.2");
+
error = thvar_init();
if (error)
goto revert_log;
revert_log:
log_teardown();
PR_DEBUG_MSG("Main thread returning.");
- return error;
+just_quit:
+ return abs(error);
}
error = deltas_head_create(&list);
if (error) {
free(tmp);
- return pr_enomem();
+ return error;
}
tmp->deltas_list = list;
tmp->uri = NULL;
return 0;
}
-static void
+__dead static void
handle_child_thread(char **args, int fds[2][2])
{
/* THIS FUNCTION MUST NEVER RETURN!!! */
return 0;
}
-static void
+static int
log_buffer(char const *buffer, ssize_t read, int type, bool log_operation)
{
#define PRE_RSYNC "[RSYNC exec]: "
char *cpy, *cur, *tmp;
cpy = malloc(read + 1);
- if (cpy == NULL) {
- pr_enomem();
- return;
- }
+ if (cpy == NULL)
+ return pr_enomem();
+
strncpy(cpy, buffer, read);
cpy[read] = '\0';
cur = tmp + 1;
}
free(cpy);
+ return 0;
#undef PRE_RSYNC
}
{
char buffer[4096];
ssize_t count;
+ int error;
while (1) {
count = read(fd_pipe[type][0], buffer, sizeof(buffer));
if (count == 0)
break;
- log_buffer(buffer, count, type, log_operation);
+ error = log_buffer(buffer, count, type, log_operation);
+ if (error)
+ return error;
}
close(fd_pipe[type][0]); /* Close read end */
return 0;
TA_DEBUG_MSG("%d", error);
pr_val_debug("Child terminated with error code %d.",
error);
- if (error == -ENOMEM)
- pr_enomem();
-
if (!error)
goto release_args;
error = send_cache_reset_pdu(fd, version);
goto end;
case -ENOMEM: /* Memory allocation failure */
- pr_enomem();
+ error = pr_enomem();
goto end;
case EAGAIN: /* Too many threads */
/*
*/
string = malloc(string_len + 1); /* Include NULL chara. */
- if (!string)
+ if (string == NULL)
return pr_enomem();
memcpy(string, reader->buffer, string_len);
bool
db_slurm_bgpsec_is_filtered(struct db_slurm *db, struct router_key const *key)
{
+ unsigned char ski[RK_SKI_LEN];
struct slurm_bgpsec slurm_bgpsec;
- unsigned char *tmp;
- bool result;
- tmp = malloc(RK_SKI_LEN);
- if (tmp == NULL) {
- pr_enomem();
- return false;
- }
slurm_bgpsec.data_flag = SLURM_COM_FLAG_ASN | SLURM_BGPS_FLAG_SKI;
slurm_bgpsec.asn = key->as;
- memcpy(tmp, key->ski, RK_SKI_LEN);
- slurm_bgpsec.ski = tmp;
+ memcpy(ski, key->ski, RK_SKI_LEN);
+ slurm_bgpsec.ski = ski;
/* Router public key isn't used at filters */
slurm_bgpsec.router_public_key = NULL;
- result = bgpsec_filtered(db, &slurm_bgpsec);
- free(tmp);
- return result;
+ return bgpsec_filtered(db, &slurm_bgpsec);
}
#define ITERATE_LIST_FUNC(type, object, db_list) \
slash_pos = strrchr(mft, '/');
if (slash_pos == NULL) {
joined = malloc(ia5->size + 1);
- if (!joined)
+ if (joined == NULL)
return pr_enomem();
strncpy(joined, (char *) ia5->buf, ia5->size);
joined[ia5->size] = '\0';
dir_len = (slash_pos + 1) - mft;
joined = malloc(dir_len + ia5->size + 1);
- if (!joined)
+ if (joined == NULL)
return pr_enomem();
strncpy(joined, mft, dir_len);