Changeset 1a3b953 in mainline
- Timestamp:
- 2012-08-20T00:22:19Z (12 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 0784869
- Parents:
- 5e514c0
- Location:
- uspace
- Files:
-
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/dist/src/bithenge/test.sh
r5e514c0 r1a3b953 7 7 if type valgrind >/dev/null 2>&1 8 8 then 9 BITHENGE="valgrind -q --show-reachable=yes ${BITHENGE}"9 BITHENGE="valgrind -q --show-reachable=yes --error-exitcode=64 ${BITHENGE}" 10 10 else 11 11 echo "Valgrind not found." -
uspace/lib/bithenge/blob.c
r5e514c0 r1a3b953 58 58 assert(ops->size); 59 59 60 if (bithenge_should_fail()) 61 return ENOMEM; 62 60 63 blob->base.type = BITHENGE_NODE_BLOB; 61 64 blob->base.refs = 1; … … 195 198 { 196 199 memory_blob_t *blob = blob_as_memory(base); 200 if (bithenge_should_fail()) 201 return EIO; 197 202 *size = blob->size; 198 203 return EOK; … … 223 228 .destroy = memory_destroy, 224 229 }; 225 226 /** Create a blob node from data. Unlike with @a227 * bithenge_blob_t::bithenge_new_blob_from_buffer, the data is copied into a228 * new buffer and the original data can be changed after this call. The blob229 * must be freed with @a bithenge_node_t::bithenge_node_destroy after it is230 * used.231 * @memberof bithenge_blob_t232 * @param[out] out Stores the created blob node.233 * @param[in] data The data.234 * @param len The length of the data.235 * @return EOK on success or an error code from errno.h. */236 int bithenge_new_blob_from_data(bithenge_node_t **out, const void *data,237 size_t len)238 {239 int rc;240 assert(data || !len);241 242 memory_blob_t *blob = malloc(sizeof(*blob));243 if (!blob)244 return ENOMEM;245 rc = bithenge_init_random_access_blob(memory_as_blob(blob),246 &memory_ops);247 if (rc != EOK) {248 free(blob);249 return rc;250 }251 char *buffer = malloc(len);252 if (!buffer) {253 free(blob);254 return rc;255 }256 memcpy(buffer, data, len);257 blob->buffer = buffer;258 blob->size = len;259 blob->needs_free = true;260 *out = bithenge_blob_as_node(memory_as_blob(blob));261 return EOK;262 }263 230 264 231 /** Create a blob node from a buffer. The buffer must exist as long as the blob … … 280 247 281 248 memory_blob_t *blob = malloc(sizeof(*blob)); 282 if (!blob) 283 return ENOMEM; 249 if (!blob) { 250 rc = ENOMEM; 251 goto error; 252 } 284 253 rc = bithenge_init_random_access_blob(memory_as_blob(blob), 285 254 &memory_ops); 286 if (rc != EOK) { 287 free(blob); 288 return rc; 289 } 255 if (rc != EOK) 256 goto error; 290 257 blob->buffer = buffer; 291 258 blob->size = len; … … 293 260 *out = bithenge_blob_as_node(memory_as_blob(blob)); 294 261 return EOK; 295 } 262 263 error: 264 if (needs_free) 265 free((void *)buffer); 266 free(blob); 267 return rc; 268 } 269 270 /** Create a blob node from data. Unlike with @a 271 * bithenge_blob_t::bithenge_new_blob_from_buffer, the data is copied into a 272 * new buffer and the original data can be changed after this call. The blob 273 * must be freed with @a bithenge_node_t::bithenge_node_destroy after it is 274 * used. 275 * @memberof bithenge_blob_t 276 * @param[out] out Stores the created blob node. 277 * @param[in] data The data. 278 * @param len The length of the data. 279 * @return EOK on success or an error code from errno.h. */ 280 int bithenge_new_blob_from_data(bithenge_node_t **out, const void *data, 281 size_t len) 282 { 283 char *buffer = malloc(len); 284 if (!buffer) 285 return ENOMEM; 286 memcpy(buffer, data, len); 287 288 return bithenge_new_blob_from_buffer(out, buffer, len, true); 289 } 290 291 296 292 297 293 typedef struct { -
uspace/lib/bithenge/compound.c
r5e514c0 r1a3b953 38 38 #include "compound.h" 39 39 #include "expression.h" 40 #include "os.h" 40 41 #include "transform.h" 41 42 #include "tree.h" -
uspace/lib/bithenge/expression.c
r5e514c0 r1a3b953 40 40 #include "blob.h" 41 41 #include "expression.h" 42 #include "os.h" 42 43 #include "transform.h" 43 44 #include "tree.h" … … 53 54 assert(ops->evaluate); 54 55 assert(ops->destroy); 56 if (bithenge_should_fail()) 57 return ENOMEM; 55 58 self->ops = ops; 56 59 self->refs = 1; … … 304 307 int bithenge_in_node_expression(bithenge_expression_t **out) 305 308 { 309 if (bithenge_should_fail()) 310 return ENOMEM; 306 311 bithenge_expression_inc_ref(&in_node_expression); 307 312 *out = &in_node_expression; -
uspace/lib/bithenge/failure.c
r5e514c0 r1a3b953 36 36 37 37 #include <errno.h> 38 #include <execinfo.h> 38 39 #include <fcntl.h> 39 40 #include <stdio.h> … … 45 46 #define BITHENGE_FAILURE_DECLS_ONLY 1 46 47 #include "failure.h" 48 #include "os.h" 47 49 48 50 /* This file raises fake errors from system calls, to test that Bithenge … … 54 56 * correctly (exit code is 1), the main process continues without errors. If 55 57 * the child process has a problem, the main process raises the fake error 56 * again and shows all stdout and stderr output. For speed, failures only occur57 * for some system calls after the first 128.58 * again and shows all stdout and stderr output. For speed, errors are only 59 * raised when part of the backtrace has not been seen before. 58 60 * 59 61 * BITHENGE_FAILURE_INDEX set: the program runs normally until system call … … 61 63 * call. */ 62 64 65 static int g_initialized = 0; 63 66 static int g_failure_index = -1; 64 static int g_failure_index_selected = -2; 65 66 static int should_fail(void) 67 static int g_failure_index_selected = -1; 68 69 typedef struct backtrace_item { 70 struct backtrace_item *next; 71 void *backtrace_item; 72 } backtrace_item_t; 73 74 static backtrace_item_t *g_backtrace_items = NULL; 75 76 static void atexit_handler(void) 77 { 78 while (g_backtrace_items) { 79 backtrace_item_t *first = g_backtrace_items; 80 g_backtrace_items = first->next; 81 free(first); 82 } 83 } 84 85 static inline void initialize(void) 86 { 87 g_initialized = 1; 88 int rc = atexit(atexit_handler); 89 if (rc) 90 exit(127); 91 92 char *sel_str = getenv("BITHENGE_FAILURE_INDEX"); 93 if (sel_str) 94 g_failure_index_selected = strtol(sel_str, NULL, 10); 95 } 96 97 /* Record a hit for a backtrace address and return whether this is the first 98 * hit. */ 99 static inline int backtrace_item_hit(void *addr) 100 { 101 backtrace_item_t **bip; 102 for (bip = &g_backtrace_items; *bip; bip = &(*bip)->next) { 103 backtrace_item_t *bi = *bip; 104 if (bi->backtrace_item == addr) { 105 /* Keep frequently accessed items near the front. */ 106 *bip = bi->next; 107 bi->next = g_backtrace_items; 108 g_backtrace_items = bi; 109 return 0; 110 } 111 } 112 113 /* No item found; create one. */ 114 backtrace_item_t *i = malloc(sizeof(*i)); 115 if (!i) 116 exit(127); 117 i->next = g_backtrace_items; 118 i->backtrace_item = addr; 119 g_backtrace_items = i; 120 return 1; 121 } 122 123 int bithenge_should_fail(void) 67 124 { 68 125 g_failure_index++; 69 126 70 if (g_failure_index_selected == -2) { 71 char *sel_str = getenv("BITHENGE_FAILURE_INDEX"); 72 if (sel_str) { 73 g_failure_index_selected = strtol(sel_str, NULL, 10); 74 } else { 75 g_failure_index_selected = -1; 76 } 77 } else if (g_failure_index_selected != -1) { 127 if (!g_initialized) 128 initialize(); 129 130 if (g_failure_index_selected != -1) { 78 131 if (g_failure_index == g_failure_index_selected) 79 132 return 1; /* breakpoint here */ … … 81 134 } 82 135 83 /* Only fail half the time after 128 failures, 1/4 the time after 256 84 * failures, 1/8 the time after 512 failures... */ 85 int index = g_failure_index; 86 while (index >= 128) { 87 int test = (index & (64 | 1)); 88 if (test == (64 | 1) || test == 0) 89 return 0; 90 index >>= 1; 91 } 136 /* If all backtrace items have been seen already, there's no need to 137 * try raising an error. */ 138 void *trace[256]; 139 int size = backtrace(trace, 256); 140 int raise_error = 0; 141 for (int i = 0; i < size; i++) { 142 if (backtrace_item_hit(trace[i])) 143 raise_error = 1; 144 } 145 if (!raise_error) 146 return 0; 92 147 93 148 if (!fork()) { 94 /* Child */149 /* Child silently fails. */ 95 150 int null = open("/dev/null", O_WRONLY); 96 151 if (null == -1) … … 102 157 } 103 158 104 /* Parent */159 /* Parent checks whether child failed correctly. */ 105 160 int status; 106 161 wait(&status); … … 108 163 return 0; 109 164 110 /* The child had an error! We couldn't see it because stdout and stderr111 * were redirected, and we couldn't debug it easily because it was a112 * separate process. Do it againwithout redirecting or forking. */165 /* The child had an error! We couldn't easily debug it because it was 166 * in a separate process with redirected stdout and stderr. Do it again 167 * without redirecting or forking. */ 113 168 fprintf(stderr, "** Fake error raised here (BITHENGE_FAILURE_INDEX=%d)\n", 114 169 g_failure_index); … … 118 173 void *bithenge_failure_malloc(size_t size) 119 174 { 120 if ( should_fail())175 if (bithenge_should_fail()) 121 176 return NULL; 122 177 return malloc(size); … … 125 180 void *bithenge_failure_realloc(void *ptr, size_t size) 126 181 { 127 if ( should_fail())182 if (bithenge_should_fail()) 128 183 return NULL; 129 184 return realloc(ptr, size); … … 132 187 ssize_t bithenge_failure_read(int fd, void *buf, size_t count) 133 188 { 134 if ( should_fail()) {189 if (bithenge_should_fail()) { 135 190 errno = EIO; 136 191 return -1; … … 141 196 off_t bithenge_failure_lseek(int fd, off_t offset, int whither) 142 197 { 143 if ( should_fail()) {198 if (bithenge_should_fail()) { 144 199 errno = EINVAL; 145 200 return (off_t) -1; … … 148 203 } 149 204 205 int bithenge_failure_ferror(FILE *stream) 206 { 207 if (bithenge_should_fail()) 208 return 1; 209 return ferror(stream); 210 } 211 212 char *bithenge_failure_str_ndup(const char *s, size_t max_len) 213 { 214 if (bithenge_should_fail()) 215 return NULL; 216 return str_ndup(s, max_len); 217 } 218 219 int bithenge_failure_open(const char *pathname, int flags) 220 { 221 if (bithenge_should_fail()) { 222 errno = EACCES; 223 return -1; 224 } 225 return open(pathname, flags); 226 } 227 228 int bithenge_failure_fstat(int fd, struct stat *buf) 229 { 230 if (bithenge_should_fail()) { 231 errno = EIO; 232 return -1; 233 } 234 return fstat(fd, buf); 235 } 236 150 237 /** @} 151 238 */ -
uspace/lib/bithenge/failure.h
r5e514c0 r1a3b953 38 38 #define BITHENGE_FAILURE_H_ 39 39 40 #include <fcntl.h> 41 #include <stdio.h> 40 42 #include <stdlib.h> 43 #include <sys/stat.h> 41 44 #include <sys/types.h> 42 45 #include <unistd.h> 46 #include "os.h" 43 47 48 int bithenge_should_fail(void); 44 49 void *bithenge_failure_malloc(size_t); 45 50 void *bithenge_failure_realloc(void *, size_t); 46 51 ssize_t bithenge_failure_read(int, void *, size_t); 47 52 off_t bithenge_failure_lseek(int, off_t, int); 53 int bithenge_failure_ferror(FILE *); 54 char *bithenge_failure_str_ndup(const char *, size_t); 55 int bithenge_failure_open(const char *, int); 56 int bithenge_failure_fstat(int, struct stat *); 48 57 49 58 #ifndef BITHENGE_FAILURE_DECLS_ONLY … … 52 61 #define read bithenge_failure_read 53 62 #define lseek bithenge_failure_lseek 63 #define ferror bithenge_failure_ferror 64 #define str_ndup bithenge_failure_str_ndup 65 #define open bithenge_failure_open 66 #define fstat bithenge_failure_fstat 54 67 #endif 55 68 -
uspace/lib/bithenge/file.c
r5e514c0 r1a3b953 79 79 return ELIMIT; 80 80 if (lseek(blob->fd, offset, SEEK_SET) < 0) 81 return errno == EINVAL ? EIO : EINVAL;81 return errno == EINVAL ? EIO : errno; 82 82 83 83 ssize_t amount_read; -
uspace/lib/bithenge/os.h
r5e514c0 r1a3b953 35 35 #ifdef BITHENGE_FAILURE_ENABLE 36 36 #include "failure.h" 37 #else 38 static inline int bithenge_should_fail(void) 39 { 40 return 0; 41 } 37 42 #endif -
uspace/lib/bithenge/transform.c
r5e514c0 r1a3b953 40 40 #include <stdlib.h> 41 41 #include "blob.h" 42 #include "os.h" 42 43 #include "print.h" 43 44 #include "transform.h" … … 62 63 assert(ops->apply || ops->prefix_apply); 63 64 assert(ops->destroy); 65 if (bithenge_should_fail()) 66 return ENOMEM; 64 67 self->ops = ops; 65 68 self->refs = 1; … … 371 374 assert(scope); 372 375 assert(i >= 0 && i < scope->num_params); 376 if (bithenge_should_fail()) { 377 bithenge_node_dec_ref(node); 378 return ENOMEM; 379 } 373 380 scope->params[i] = node; 374 381 return EOK; … … 487 494 assert(transform); 488 495 assert(bithenge_transform_num_params(transform) == 0); 496 497 if (bithenge_should_fail()) { 498 bithenge_transform_dec_ref(transform); 499 return ENOMEM; 500 } 489 501 490 502 barrier_transform_t *self = transform_as_barrier(base); -
uspace/lib/bithenge/tree.c
r5e514c0 r1a3b953 198 198 int bithenge_new_empty_internal_node(bithenge_node_t **out) 199 199 { 200 if (bithenge_should_fail()) 201 return ENOMEM; 200 202 bithenge_node_inc_ref(&empty_internal_node); 201 203 *out = &empty_internal_node; … … 301 303 { 302 304 assert(out); 305 if (bithenge_should_fail()) 306 return ENOMEM; 303 307 *out = value ? &true_node : &false_node; 304 308 (*out)->refs++;
Note:
See TracChangeset
for help on using the changeset viewer.