Merge pull request #1659 from stepancheg/verify

IDRIS2_VERIFY macro
This commit is contained in:
Edwin Brady 2021-07-16 09:01:31 +01:00 committed by GitHub
commit 6143508f7b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 73 additions and 35 deletions

View File

@ -1,13 +1,18 @@
#include "idris_directory.h"
#include <dirent.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#include <stdlib.h>
#include <unistd.h>
#include "idris_util.h"
char* idris2_currentDirectory() {
char* cwd = malloc(1024); // probably ought to deal with the unlikely event of this being too small
IDRIS2_VERIFY(cwd, "malloc failed");
return getcwd(cwd, 1024); // Freed by RTS
}
@ -34,6 +39,7 @@ void* idris2_openDir(char* dir) {
return NULL;
} else {
DirInfo* di = malloc(sizeof(DirInfo));
IDRIS2_VERIFY(di, "malloc failed");
di->dirptr = d;
di->error = 0;
@ -44,7 +50,7 @@ void* idris2_openDir(char* dir) {
void idris2_closeDir(void* d) {
DirInfo* di = (DirInfo*)d;
closedir(di->dirptr);
IDRIS2_VERIFY(closedir(di->dirptr) == 0, "closedir failed: %s", strerror(errno));
free(di);
}

View File

@ -1,12 +1,13 @@
#include "getline.h"
#include "idris_file.h"
#include <fcntl.h>
#include <errno.h>
#include <sys/stat.h>
#include <time.h>
#include <sys/time.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
#ifdef _WIN32
@ -15,6 +16,8 @@
#include <sys/select.h>
#endif
#include "idris_util.h"
FILE* idris2_openFile(char* name, char* mode) {
#ifdef _WIN32
FILE *f = win32_u8fopen(name, mode);
@ -25,7 +28,7 @@ FILE* idris2_openFile(char* name, char* mode) {
}
void idris2_closeFile(FILE* f) {
fclose(f);
IDRIS2_VERIFY(fclose(f) == 0, "fclose failed: %s", strerror(errno));
}
int idris2_fileError(FILE* f) {
@ -90,10 +93,11 @@ void *idris2_popen(const char *cmd, const char *mode) {
void idris2_pclose(void *stream) {
#ifdef _WIN32
_pclose(stream);
int r = _pclose(stream);
#else
pclose(stream);
int r = pclose(stream);
#endif
IDRIS2_VERIFY(r != -1, "pclose failed");
}
// seek through the next newline, consuming and

View File

@ -1,15 +1,13 @@
#include "idris_memory.h"
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "idris_util.h"
void* idris2_malloc(int size) {
if (size < 0) {
fprintf(stderr, "malloc negative argument: %d\n", size);
abort();
}
IDRIS2_VERIFY(size >= 0, "malloc negative argument: %d", size);
if (size == 0) {
// Do not depend on platform-speific behavior of malloc.
@ -17,10 +15,7 @@ void* idris2_malloc(int size) {
}
void* ptr = malloc(size);
if (!ptr) {
fprintf(stderr, "malloc failed: %s\n", strerror(errno));
abort();
}
IDRIS2_VERIFY(ptr, "malloc failed: %s", strerror(errno));
return ptr;
}

View File

@ -8,6 +8,8 @@
#include <stdio.h>
#include <string.h>
#include "idris_util.h"
#ifndef _WIN32
#include <netinet/in.h>
#include <arpa/inet.h>

View File

@ -1,11 +1,14 @@
#include "idris_signal.h"
#include <assert.h>
#include <errno.h>
#include <limits.h>
#include <signal.h>
#include <stdatomic.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "idris_util.h"
static_assert(ATOMIC_LONG_LOCK_FREE == 2,
"when not lock free, atomic functions are not async-signal-safe");
@ -14,20 +17,14 @@ static_assert(ATOMIC_LONG_LOCK_FREE == 2,
static atomic_long signal_count[N_SIGNALS];
void _collect_signal(int signum) {
if (signum < 0 || signum >= N_SIGNALS) {
abort();
}
IDRIS2_VERIFY(signum >= 0 && signum < N_SIGNALS, "signal number out of range: %d", signum);
long prev = atomic_fetch_add(&signal_count[signum], 1);
if (prev == LONG_MAX) {
// Practically impossible, but better crash explicitly
fprintf(stderr, "signal count overflow\n");
abort();
}
IDRIS2_VERIFY(prev != LONG_MAX, "signal count overflow");
#ifdef _WIN32
//re-instate signal handler
signal(signum, _collect_signal);
IDRIS2_VERIFY(signal(signum, _collect_signal) != SIG_ERR, "signal failed: %s", strerror(errno));
#endif
}
@ -77,11 +74,7 @@ int handle_next_collected_signal() {
if (count == 0) {
break;
}
if (count < 0) {
// Practically impossible, but better crash explicitly
fprintf(stderr, "signal count overflow\n");
abort();
}
IDRIS2_VERIFY(count >= 0, "signal count overflow");
if (atomic_compare_exchange_strong(&signal_count[signum], &count, count - 1)) {
return signum;
}

View File

@ -68,6 +68,8 @@ void idris2_sleep(int sec) {
t.tv_sec = sec;
t.tv_nsec = 0;
// TODO: `nanosleep` can fail
// TODO: `nanosleep` can return early due to interrupt
nanosleep(&t, NULL);
#endif
}

16
support/c/idris_util.c Normal file
View File

@ -0,0 +1,16 @@
#include "idris_util.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
void idris2_verify_failed(const char* file, int line, const char* cond, const char* fmt, ...) {
va_list ap;
va_start(ap, fmt);
char message[1000];
snprintf(message, sizeof(message), fmt, ap);
fprintf(stderr, "assertion failed in %s:%d: %s: %s\n", file, line, cond, message);
abort();
}

20
support/c/idris_util.h Normal file
View File

@ -0,0 +1,20 @@
#pragma once
#include <stdnoreturn.h>
// Utilities used by FFI code.
// Crash is the condition is false.
#define IDRIS2_VERIFY(cond, ...) \
do { \
if (!(cond)) { \
idris2_verify_failed(__FILE__, __LINE__, #cond, __VA_ARGS__); \
} \
} while (0)
// Used by `IDRIS2_VERIFY`, do not use directly.
noreturn void idris2_verify_failed(const char* file, int line, const char* cond, const char* fmt, ...)
#if defined(__clang__) || defined(__GNUC__)
__attribute__ ((format(printf, 4, 5)))
#endif
;