static void command_get_signal_list(char * token, Channel * c) { int err = 0; char id[256]; pid_t pid; json_read_string(&c->inp, id, sizeof(id)); if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX); if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX); pid = id2pid(id, NULL); write_stringz(&c->out, "R"); write_stringz(&c->out, token); /* pid is ignored, same signal list for all */ write_errno(&c->out, err); if (err) { write_stringz(&c->out, "null"); } else { int i = 0; int n = 0; write_stream(&c->out, '['); for (i = 0; i < 32; i++) { char * name = signal_name(i); char * desc = signal_description(i); if (name != NULL || desc != NULL) { if (n > 0) write_stream(&c->out, ','); write_stream(&c->out, '{'); json_write_string(&c->out, "Index"); write_stream(&c->out, ':'); json_write_long(&c->out, i); if (name != NULL) { write_stream(&c->out, ','); json_write_string(&c->out, "Name"); write_stream(&c->out, ':'); json_write_string(&c->out, name); } if (desc != NULL) { write_stream(&c->out, ','); json_write_string(&c->out, "Description"); write_stream(&c->out, ':'); json_write_string(&c->out, desc); } write_stream(&c->out, ','); json_write_string(&c->out, "Code"); write_stream(&c->out, ':'); json_write_ulong(&c->out, signal_code(i)); write_stream(&c->out, '}'); n++; } } write_stream(&c->out, ']'); write_stream(&c->out, 0); } write_stream(&c->out, MARKER_EOM); }
/* This function is the SIGSEGV handler for the virtual memory system. If the * faulting address is within the user-space virtual memory pool then this * function responds appropriately to allow the faulting operation to be * retried. If the faulting address falls outside of the virtual memory pool * then the segmentation fault is reported as an error. * * While a SIGSEGV is being processed, SIGALRM signals are blocked. Therefore * a timer interrupt will never interrupt the segmentation-fault handler. */ static void sigsegv_handler(int signum, siginfo_t *infop, void *data) { void *addr; page_t page; /* Only handle SIGSEGVs addresses in range */ addr = infop->si_addr; if (addr < vmem_start || addr >= vmem_end) { fprintf(stderr, "segmentation fault at address %p\n", addr); abort(); } num_faults++; /* Figure out what page generated the fault. */ page = addr_to_page(addr); assert(page < NUM_PAGES); #if VERBOSE fprintf(stderr, "================================================================\n"); fprintf(stderr, "SIGSEGV: Address %p, Page %u, Code %s (%d)\n", addr, page, signal_code(infop->si_code), infop->si_code); #endif /* We really can't handle any other type of code. On Linux this should be * fine though. */ assert(infop->si_code == SEGV_MAPERR || infop->si_code == SEGV_ACCERR); /* Map the page into memory so that the fault can be resolved. Of course, * this may result in some other page being unmapped. */ /* Handle unmapped address (SEGV_MAPERR). */ if (infop->si_code == SEGV_MAPERR) { /* Evict a page. */ assert(num_resident <= max_resident); if (num_resident == max_resident) { page_t victim = choose_victim_page(); assert(is_page_resident(victim)); unmap_page(victim); assert(!is_page_resident(victim)); } /* * There should now be space, so load the new page. No permissions * initially. */ assert(num_resident < max_resident); map_page(page, PAGEPERM_NONE); } /* Handle unpermitted access (SEGV_ACCERR). */ else { /* Regardless of attempted read or write, it is now accessed. */ set_page_accessed(page); assert(is_page_accessed(page)); switch(get_page_permission(page)) { case PAGEPERM_NONE: /* * Tried to read or write. Give read access, if it was a write * then it will segfault again and read-write access will be * given then. */ set_page_permission(page, PAGEPERM_READ); break; case PAGEPERM_READ: /* Tried to write, so make it read-write access. */ set_page_permission(page, PAGEPERM_RDWR); /* Since it is a write it is also dirty. */ set_page_dirty(page); assert(is_page_dirty(page)); break; case PAGEPERM_RDWR: fprintf(stderr, "sigsegv_handler: got unpermitted access error \ on page that already has read-write permission.\n"); abort(); break; } } }