Example #1
0
/*
  test references 
*/
static bool test_ref3(void)
{
	void *root, *p1, *p2, *ref, *r1;

	printf("test: ref3 [\nPARENT REFERENCE FREE\n]\n");

	root = talloc_named_const(NULL, 0, "root");
	p1 = talloc_named_const(root, 1, "p1");
	p2 = talloc_named_const(root, 1, "p2");
	r1 = talloc_named_const(p1, 1, "r1");
	ref = talloc_reference(p2, r1);
	talloc_report_full(root, stderr);

	CHECK_BLOCKS("ref3", p1, 2);
	CHECK_BLOCKS("ref3", p2, 2);
	CHECK_BLOCKS("ref3", r1, 1);

	fprintf(stderr, "Freeing p1\n");
	talloc_free(p1);
	talloc_report_full(root, stderr);

	CHECK_BLOCKS("ref3", p2, 2);
	CHECK_BLOCKS("ref3", r1, 1);

	fprintf(stderr, "Freeing p2\n");
	talloc_free(p2);
	talloc_report_full(root, stderr);

	CHECK_SIZE("ref3", root, 0);

	talloc_free(root);

	printf("success: ref3\n");
	return true;
}
Example #2
0
void log_talloc_report(TALLOC_CTX *ctx)
{
	FILE *fd;
	char const *null_ctx = NULL;
	int i = 0;

	if (ctx) {
		null_ctx = talloc_get_name(NULL);
	}

	fd = fdopen(default_log.fd, "w");
	if (!fd) {
		ERROR("Couldn't write memory report, fdopen failed: %s", fr_syserror(errno));

		return;
	}

	if (!ctx) {
		talloc_report_full(NULL, fd);
	} else {
		do {
			INFO("Context level %i", i++);

			talloc_report_full(ctx, fd);
		} while ((ctx = talloc_parent(ctx)) && (talloc_get_name(ctx) != null_ctx));  /* Stop before we hit NULL ctx */
	}

	fclose(fd);
}
Example #3
0
static bool test_loop(void)
{
	void *top = talloc_new(NULL);
	char *parent;
	struct req1 {
		char *req2, *req3;
	} *req1;

	printf("test: loop\n# TALLOC LOOP DESTRUCTION\n");

	parent = talloc_strdup(top, "parent");
	req1 = talloc(parent, struct req1);
	req1->req2 = talloc_strdup(req1, "req2");  
	talloc_set_destructor(req1->req2, test_loop_destructor);
	req1->req3 = talloc_strdup(req1, "req3");
	(void)talloc_reference(req1->req3, req1);
	talloc_report_full(top, stderr);
	talloc_free(parent);
	talloc_report_full(top, stderr);
	talloc_report_full(NULL, stderr);
	talloc_free(top);

	torture_assert("loop", loop_destructor_count == 1, 
				   "FAILED TO FIRE LOOP DESTRUCTOR\n");
	loop_destructor_count = 0;

	printf("success: loop\n");
	return true;
}
Example #4
0
/*
  test references 
*/
static bool test_ref1(void)
{
	void *root, *p1, *p2, *ref, *r1;

	printf("test: ref1\n# SINGLE REFERENCE FREE\n");

	root = talloc_named_const(NULL, 0, "root");
	p1 = talloc_named_const(root, 1, "p1");
	p2 = talloc_named_const(p1, 1, "p2");
	talloc_named_const(p1, 1, "x1");
	talloc_named_const(p1, 2, "x2");
	talloc_named_const(p1, 3, "x3");

	r1 = talloc_named_const(root, 1, "r1");	
	ref = talloc_reference(r1, p2);
	talloc_report_full(root, stderr);

	CHECK_BLOCKS("ref1", p1, 5);
	CHECK_BLOCKS("ref1", p2, 1);
	CHECK_BLOCKS("ref1", ref, 1);
	CHECK_BLOCKS("ref1", r1, 2);

	fprintf(stderr, "Freeing p2\n");
	talloc_unlink(r1, p2);
	talloc_report_full(root, stderr);

	CHECK_BLOCKS("ref1", p1, 5);
	CHECK_BLOCKS("ref1", p2, 1);
	CHECK_BLOCKS("ref1", r1, 1);

	fprintf(stderr, "Freeing p1\n");
	talloc_free(p1);
	talloc_report_full(root, stderr);

	CHECK_BLOCKS("ref1", r1, 1);

	fprintf(stderr, "Freeing r1\n");
	talloc_free(r1);
	talloc_report_full(NULL, stderr);

	fprintf(stderr, "Testing NULL\n");
	if (talloc_reference(root, NULL)) {
		return false;
	}

	CHECK_BLOCKS("ref1", root, 1);

	CHECK_SIZE("ref1", root, 0);

	talloc_free(root);
	printf("success: ref1\n");
	return true;
}
Example #5
0
/*
  test references 
*/
static bool test_ref2(void)
{
	void *root, *p1, *p2, *ref, *r1;

	printf("test: ref2\n# DOUBLE REFERENCE FREE\n");
	root = talloc_named_const(NULL, 0, "root");
	p1 = talloc_named_const(root, 1, "p1");
	talloc_named_const(p1, 1, "x1");
	talloc_named_const(p1, 1, "x2");
	talloc_named_const(p1, 1, "x3");
	p2 = talloc_named_const(p1, 1, "p2");

	r1 = talloc_named_const(root, 1, "r1");	
	ref = talloc_reference(r1, p2);
	talloc_report_full(root, stderr);

	CHECK_BLOCKS("ref2", p1, 5);
	CHECK_BLOCKS("ref2", p2, 1);
	CHECK_BLOCKS("ref2", r1, 2);

	fprintf(stderr, "Freeing ref\n");
	talloc_unlink(r1, ref);
	talloc_report_full(root, stderr);

	CHECK_BLOCKS("ref2", p1, 5);
	CHECK_BLOCKS("ref2", p2, 1);
	CHECK_BLOCKS("ref2", r1, 1);

	fprintf(stderr, "Freeing p2\n");
	talloc_free(p2);
	talloc_report_full(root, stderr);

	CHECK_BLOCKS("ref2", p1, 4);
	CHECK_BLOCKS("ref2", r1, 1);

	fprintf(stderr, "Freeing p1\n");
	talloc_free(p1);
	talloc_report_full(root, stderr);

	CHECK_BLOCKS("ref2", r1, 1);

	fprintf(stderr, "Freeing r1\n");
	talloc_free(r1);
	talloc_report_full(root, stderr);

	CHECK_SIZE("ref2", root, 0);

	talloc_free(root);
	printf("success: ref2\n");
	return true;
}
Example #6
0
/** Generate a talloc memory report for a context and print to stderr/stdout
 *
 * @param ctx to generate a report for, may be NULL in which case the root context is used.
 */
int fr_log_talloc_report(TALLOC_CTX *ctx)
{
#define TALLOC_REPORT_MAX_DEPTH 20

	FILE *log;
	int fd;

	fd = dup(fr_fault_log_fd);
	if (fd < 0) {
		fr_strerror_printf("Couldn't write memory report, failed to dup log fd: %s", fr_syserror(errno));
		return -1;
	}
	log = fdopen(fd, "w");
	if (!log) {
		close(fd);
		fr_strerror_printf("Couldn't write memory report, fdopen failed: %s", fr_syserror(errno));
		return -1;
	}

	if (!ctx) {
		fprintf(log, "Current state of talloced memory:\n");
		talloc_report_full(talloc_null_ctx, log);
	} else {
		int i;

		fprintf(log, "Talloc chunk lineage:\n");
		fprintf(log, "%p (%s)", ctx, talloc_get_name(ctx));

		i = 0;
		while ((i < TALLOC_REPORT_MAX_DEPTH) && (ctx = talloc_parent(ctx))) {
			fprintf(log, " < %p (%s)", ctx, talloc_get_name(ctx));
			i++;
		}
		fprintf(log, "\n");

		i = 0;
		do {
			fprintf(log, "Talloc context level %i:\n", i++);
			talloc_report_full(ctx, log);
		} while ((ctx = talloc_parent(ctx)) &&
			 (i < TALLOC_REPORT_MAX_DEPTH) &&
			 (talloc_parent(ctx) != talloc_autofree_ctx) &&	/* Stop before we hit the autofree ctx */
			 (talloc_parent(ctx) != talloc_null_ctx));  	/* Stop before we hit NULL ctx */
	}

	fclose(log);

	return 0;
}
Example #7
0
/*
  dump talloc memory hierarchy, returning it as a blob to the client
 */
int32_t ctdb_dump_memory(struct ctdb_context *ctdb, TDB_DATA *outdata)
{
    /* dump to a file, then send the file as a blob */
    FILE *f;
    long fsize;
    f = tmpfile();
    if (f == NULL) {
        DEBUG(DEBUG_ERR,(__location__ " Unable to open tmpfile - %s\n", strerror(errno)));
        return -1;
    }
    talloc_report_full(NULL, f);
    fsize = ftell(f);
    if (fsize == -1) {
        DEBUG(DEBUG_ERR, (__location__ " Unable to get file size - %s\n",
                          strerror(errno)));
        fclose(f);
        return -1;
    }
    rewind(f);
    outdata->dptr = talloc_size(outdata, fsize);
    if (outdata->dptr == NULL) {
        fclose(f);
        CTDB_NO_MEMORY(ctdb, outdata->dptr);
    }
    outdata->dsize = fread(outdata->dptr, 1, fsize, f);
    fclose(f);
    if (outdata->dsize != fsize) {
        DEBUG(DEBUG_ERR,(__location__ " Unable to read tmpfile\n"));
        return -1;
    }
    return 0;
}
Example #8
0
static void sig_handler(int signr)
{
	switch (signr) {
	case SIGTERM:
	case SIGINT:
		tbus_close();
		talloc_report_full(gsmd_tallocs, stderr);
		exit(0);
		break;
	case SIGUSR1:
		talloc_report_full(gsmd_tallocs, stderr);
	case SIGALRM:
		gsmd_timer_check_n_run();
		break;
	}
}
int main(void)
{
    int number_failed;
    int memdebug;
    int error;
    
    // Check if memdebug enabled
    memdebug = getenv("MEMDEBUG") ? atoi(getenv("MEMDEBUG")) : 0;
    if( memdebug ) {
        talloc_enable_leak_report_full();
    }
    
    // Set up test suite
    Suite * s = parser_suite();
    SRunner * sr = srunner_create(s);
    if( IS_WIN || memdebug ) {
        srunner_set_fork_status(sr, CK_NOFORK);
    }
    srunner_run_all(sr, CK_ENV);
    number_failed = srunner_ntests_failed(sr);
    srunner_free(sr);
    error = (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
    
    // Generate report for memdebug
    if( memdebug ) {
        talloc_report_full(NULL, stderr);
    }
    
    // Return
    return error;
}
Example #10
0
static void signal_handler(int signal)
{
	fprintf(stdout, "signal %u received\n", signal);

	switch (signal) {
	case SIGINT:
		bsc_shutdown_net(bsc_gsmnet);
		osmo_signal_dispatch(SS_GLOBAL, S_GLOBAL_SHUTDOWN, NULL);
		sleep(3);
		exit(0);
		break;
	case SIGABRT:
		/* in case of abort, we want to obtain a talloc report
		 * and then return to the caller, who will abort the process */
	case SIGUSR1:
		talloc_report(tall_vty_ctx, stderr);
		talloc_report_full(tall_bsc_ctx, stderr);
		break;
	case SIGUSR2:
		if (!bsc_gsmnet->msc_data)
			return;
		if (!bsc_gsmnet->msc_data->msc_con)
			return;
		if (!bsc_gsmnet->msc_data->msc_con->is_connected)
			return;
		bsc_msc_lost(bsc_gsmnet->msc_data->msc_con);
		break;
	default:
		break;
	}
}
Example #11
0
/*
 * Test activating the IWbemLevel1Login interface asynchronously.
 */
static void torture_wbem_login_async_cont(struct composite_context *ctx)
{
    struct composite_context *c = NULL;
    BOOL *pRet = NULL;
    struct IUnknown **mqi = NULL;
    NTSTATUS status;

    /* retrieve the parent composite context */
    c = talloc_get_type(ctx->async.private_data, struct composite_context);
    if (!composite_is_ok(c)) return;

    pRet = (BOOL *)c->private_data;

    status = dcom_activate_recv(ctx, c, &mqi);
    *pRet = NT_STATUS_IS_OK(status);

    talloc_report_full(c, stdout);

    if (*pRet)
    {
        /*
         * Clean up by releasing the IUnknown interface on the remote server
         * and also by releasing our allocated interface pointer.
         */
        IUnknown_Release(mqi[0], c); /* really synchronous but eh */
        talloc_free(mqi);
    }

    composite_done(c);
}
Example #12
0
void sighandler(int sigset)
{
	if (sigset == SIGHUP || sigset == SIGPIPE)
		return;

	fprintf(stderr, "Signal %d received.\n", sigset);

	switch (sigset) {
	case SIGINT:
	case SIGTERM:
		/* If another signal is received afterwards, the program
		 * is terminated without finishing shutdown process.
		 */
		signal(SIGINT, SIG_DFL);
		signal(SIGHUP, SIG_DFL);
		signal(SIGTERM, SIG_DFL);
		signal(SIGPIPE, SIG_DFL);
		signal(SIGABRT, SIG_DFL);
		signal(SIGUSR1, SIG_DFL);
		signal(SIGUSR2, SIG_DFL);

		quit = 1;
		break;
	case SIGABRT:
		/* in case of abort, we want to obtain a talloc report
		 * and then return to the caller, who will abort the process
		 */
	case SIGUSR1:
	case SIGUSR2:
		talloc_report_full(tall_pcu_ctx, stderr);
		break;
	}
}
Example #13
0
/*
  test references 
*/
static bool test_unlink1(void)
{
	void *root, *p1, *p2, *ref, *r1;

	printf("test: unlink\n# UNLINK\n");

	root = talloc_named_const(NULL, 0, "root");
	p1 = talloc_named_const(root, 1, "p1");
	talloc_named_const(p1, 1, "x1");
	talloc_named_const(p1, 1, "x2");
	talloc_named_const(p1, 1, "x3");
	p2 = talloc_named_const(p1, 1, "p2");

	r1 = talloc_named_const(p1, 1, "r1");	
	ref = talloc_reference(r1, p2);
	talloc_report_full(root, stderr);

	CHECK_BLOCKS("unlink", p1, 7);
	CHECK_BLOCKS("unlink", p2, 1);
	CHECK_BLOCKS("unlink", ref, 1);
	CHECK_BLOCKS("unlink", r1, 2);

	fprintf(stderr, "Unreferencing r1\n");
	talloc_unlink(r1, p2);
	talloc_report_full(root, stderr);

	CHECK_BLOCKS("unlink", p1, 6);
	CHECK_BLOCKS("unlink", p2, 1);
	CHECK_BLOCKS("unlink", r1, 1);

	fprintf(stderr, "Freeing p1\n");
	talloc_free(p1);
	talloc_report_full(root, stderr);

	CHECK_SIZE("unlink", root, 0);

	talloc_free(root);

	printf("success: unlink\n");
	return true;
}
Example #14
0
static BOOL torture_wbem_login_async(struct torture_context *torture)
{
    BOOL ret = True;
    TALLOC_CTX *mem_ctx = talloc_init("torture_wbem_login_async");
    struct com_context *com_ctx = NULL;
    const char *binding = NULL;
    struct composite_context *c = NULL;
    struct composite_context *new_ctx = NULL;
    struct GUID clsid;
    struct GUID iid;

    /*
     * Initialize our COM and DCOM contexts.
     */
    com_init_ctx(&com_ctx, NULL);
    dcom_client_init(com_ctx, cmdline_credentials);

    /*
     * Pull our needed test arguments from the torture parameters subsystem.
     */
    binding = torture_setting_string(torture, "binding", NULL);

    /*
     * Create a new composite for our call sequence, with the private data being
     * our return flag.
     */
    c = composite_create(mem_ctx, com_ctx->event_ctx);
    c->private_data = &ret;

    /*
     * Create the parameters needed for the activation call: we need the CLSID
     * and IID for the specific interface we're after.
     */
    GUID_from_string(CLSID_WBEMLEVEL1LOGIN, &clsid);
    GUID_from_string(COM_IWBEMLEVEL1LOGIN_UUID, &iid);

    /*
     * Fire off the asynchronous activation request with all the needed
     * input parameters. Then wait for the composite to be done within the
     * context of this function, which allows all the asynchronous magic to
     * still happen.
     */
    new_ctx = dcom_activate_send(c, &clsid, binding, 1, &iid, com_ctx);
    composite_continue(c, new_ctx, torture_wbem_login_async_cont, c);
    composite_wait(new_ctx);
    talloc_free(c);
    talloc_report_full(mem_ctx, stdout);

    return ret;
}
Example #15
0
static bool test_rusty(void)
{
	void *root;
	const char *p1;

	talloc_enable_null_tracking();
	root = talloc_new(NULL);
	p1 = talloc_strdup(root, "foo");
	talloc_increase_ref_count(p1);
	talloc_report_full(root, stdout);
	talloc_free(root);
	CHECK_BLOCKS("null_context", NULL, 2);
	return true;
}
Example #16
0
static bool test_lifeless(void)
{
	void *top = talloc_new(NULL);
	char *parent, *child; 
	void *child_owner = talloc_new(NULL);

	printf("test: lifeless\n# TALLOC_UNLINK LOOP\n");

	parent = talloc_strdup(top, "parent");
	child = talloc_strdup(parent, "child");  
	(void)talloc_reference(child, parent);
	(void)talloc_reference(child_owner, child); 
	talloc_report_full(top, stderr);
	talloc_unlink(top, parent);
	talloc_unlink(top, child);
	talloc_report_full(top, stderr);
	talloc_free(top);
	talloc_free(child_owner);
	talloc_free(child);

	printf("success: lifeless\n");
	return true;
}
Example #17
0
int main(int argc, const char *argv[])
{
  TALLOC_CTX *main_ctx=talloc_new(NULL);
  FILE *f;
  char *buf;
  size_t buflen;
  TR_MSG *msg;
  
  if (argc != 2) {
    printf("Usage: %s <input file>\n\n", argv[0]);
    exit(-1);
  }

  buf=malloc(MAX_MSG_LEN);
  if (!buf) {
    printf("Allocation error.\n\n");
    exit(-1);
  }

  f=fopen(argv[1], "r");
  if (!f) {
    printf("Error opening %s for reading.\n\n", argv[1]);
    exit(-1);
  }

  printf("Reading from %s...\n", argv[1]);

  buflen=fread(buf, sizeof(char), MAX_MSG_LEN, f);
  if (buflen==0) {
    printf("File empty.\n\n");
    exit(0);
  }

  if (buflen>=MAX_MSG_LEN)
    printf("Warning: file may exceed maximum message length (%d bytes).\n", MAX_MSG_LEN);

  msg= tr_msg_decode(NULL, buf, buflen);

/*  if (rc==TRP_SUCCESS)
    trp_msg_print(msg);*/

  printf("\nEncoding...\n");

  printf("Result: \n%s\n\n", tr_msg_encode(NULL, msg));

  talloc_report_full(main_ctx, stdout);

  return 0;
}
Example #18
0
static void signal_handler(int signal)
{
	fprintf(stdout, "signal %u received\n", signal);

	switch (signal) {
	case SIGINT:
		osmo_signal_dispatch(SS_L_GLOBAL, S_L_GLOBAL_SHUTDOWN, NULL);
		sleep(1);
		exit(0);
		break;
	case SIGABRT:
		/* in case of abort, we want to obtain a talloc report
		 * and then return to the caller, who will abort the process */
	case SIGUSR1:
		talloc_report(tall_vty_ctx, stderr);
		talloc_report_full(tall_bsc_ctx, stderr);
		break;
	case SIGUSR2:
		talloc_report_full(tall_vty_ctx, stderr);
		break;
	default:
		break;
	}
}
Example #19
0
/*
  test steal
*/
static bool test_steal(void)
{
	void *root, *p1, *p2;

	printf("test: steal\n# STEAL\n");

	root = talloc_new(NULL);

	p1 = talloc_array(root, char, 10);
	CHECK_SIZE("steal", p1, 10);

	p2 = talloc_realloc(root, NULL, char, 20);
	CHECK_SIZE("steal", p1, 10);
	CHECK_SIZE("steal", root, 30);

	torture_assert("steal", talloc_steal(p1, NULL) == NULL,
		"failed: stealing NULL should give NULL\n");

	torture_assert("steal", talloc_steal(p1, p1) == p1,
		"failed: stealing to ourselves is a nop\n");
	CHECK_BLOCKS("steal", root, 3);
	CHECK_SIZE("steal", root, 30);

	talloc_steal(NULL, p1);
	talloc_steal(NULL, p2);
	CHECK_BLOCKS("steal", root, 1);
	CHECK_SIZE("steal", root, 0);

	talloc_free(p1);
	talloc_steal(root, p2);
	CHECK_BLOCKS("steal", root, 2);
	CHECK_SIZE("steal", root, 20);
	
	talloc_free(p2);

	CHECK_BLOCKS("steal", root, 1);
	CHECK_SIZE("steal", root, 0);

	talloc_free(root);

	p1 = talloc_size(NULL, 3);
	talloc_report_full(NULL, stderr);
	CHECK_SIZE("steal", NULL, 3);
	talloc_free(p1);

	printf("success: steal\n");
	return true;
}
Example #20
0
/*
 * Test activating the IWbemLevel1Login interface synchronously.
 */
static BOOL torture_wbem_login(struct torture_context *torture)
{
    BOOL ret = True;
    TALLOC_CTX *mem_ctx = talloc_init("torture_wbem_login");
    struct com_context *com_ctx = NULL;
    const char *binding = NULL;
    struct IUnknown **mqi = NULL;
    struct GUID clsid;
    struct GUID iid;
    NTSTATUS status;

    /*
     * Initialize our COM and DCOM contexts.
     */
    com_init_ctx(&com_ctx, NULL);
    dcom_client_init(com_ctx, cmdline_credentials);

    /*
     * Pull our needed test arguments from the torture parameters subsystem.
     */
    binding = torture_setting_string(torture, "binding", NULL);

    /*
     * Create the parameters needed for the activation call: we need the CLSID
     * and IID for the specific interface we're after.
     */
    GUID_from_string(CLSID_WBEMLEVEL1LOGIN, &clsid);
    GUID_from_string(COM_IWBEMLEVEL1LOGIN_UUID, &iid);

    /*
     * Activate the interface using the DCOM synchronous method call.
     */
    status = dcom_activate(com_ctx, mem_ctx, binding, &clsid, &iid, 1, &mqi);
    ret = NT_STATUS_IS_OK(status);
    if (ret)
    {
        /*
         * Clean up by releasing the IUnknown interface on the remote server
         * and also by releasing our allocated interface pointer.
         */
        IUnknown_Release(mqi[0], mem_ctx);
        talloc_free(mqi);
    }

    talloc_report_full(mem_ctx, stdout);

    return ret;
}
Example #21
0
bool
_check_leaks(TALLOC_CTX *ctx, size_t bytes, const char *location)
{
    size_t bytes_allocated;

    bytes_allocated = talloc_total_size(ctx);
    if (bytes_allocated != bytes) {
        fprintf(stderr, "Leak report for %s:\n", location);
        talloc_report_full(ctx, stderr);
        _set_leak_err_msg("%s: memory leaks detected, %zd bytes still allocated",
                          location, bytes_allocated - bytes);
        return false;
    }

    return true;
}
int main(void)
{
    int number_failed;
    Suite * s;
    SRunner * sr;
    int memdebug = 0;
    int iswin = 0;
    int error = 0;
    
#if defined(_WIN64) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN32__)
    iswin = 1;
#endif
    memdebug = getenv("MEMDEBUG") ? atoi(getenv("MEMDEBUG")) : 0;
    
    if( memdebug ) {
        talloc_enable_leak_report_full();
    }
    rootctx = talloc_new(NULL);
    
    // Load the spec
    spec_filename = getenv("handlebars_tokenizer_spec");
    if( spec_filename == NULL ) {
        spec_filename = "./spec/handlebars/spec/tokenizer.json";
    }
    error = loadSpec(spec_filename);
    if( error != 0 ) {
        goto error;
    }
    fprintf(stderr, "Loaded %lu test cases\n", tests_len);
    
    s = parser_suite();
    sr = srunner_create(s);
    if( iswin || memdebug ) {
        srunner_set_fork_status(sr, CK_NOFORK);
    }
    srunner_run_all(sr, CK_ENV);
    number_failed = srunner_ntests_failed(sr);
    srunner_free(sr);
    error = (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
    
error:
    talloc_free(rootctx);
    if( memdebug ) {
        talloc_report_full(NULL, stderr);
    }
    return error;
}
Example #23
0
File: main.c Project: jemmy655/osmo
static void signal_handler(int signal)
{
	fprintf(stderr, "signal %u received\n", signal);

	switch (signal) {
	case SIGINT:
		//osmo_signal_dispatch(SS_GLOBAL, S_GLOBAL_SHUTDOWN, NULL);
		if (!quit)
			bts_shutdown(bts, "SIGINT");
		quit++;
		break;
	case SIGABRT:
	case SIGUSR1:
	case SIGUSR2:
		talloc_report_full(tall_bts_ctx, stderr);
		break;
	default:
		break;
	}
}
Example #24
0
static void signal_handler(int signal)
{
	fprintf(stderr, "signal %u received\n", signal);

	switch (signal) {
	case SIGINT:
	case SIGTERM:
		sysmobts_check_temp(no_eeprom_write);
		sysmobts_update_hours(no_eeprom_write);
		exit(0);
		break;
	case SIGABRT:
	case SIGUSR1:
	case SIGUSR2:
		talloc_report_full(tall_mgr_ctx, stderr);
		break;
	default:
		break;
	}
}
Example #25
0
static bool test_free_children(void)
{
	void *root;
	const char *p1, *p2, *name, *name2;

	talloc_enable_null_tracking();
	root = talloc_new(NULL);
	p1 = talloc_strdup(root, "foo1");
	p2 = talloc_strdup(p1, "foo2");

	talloc_set_name(p1, "%s", "testname");
	talloc_free_children(p1);
	/* check its still a valid talloc ptr */
	talloc_get_size(talloc_get_name(p1));
	if (strcmp(talloc_get_name(p1), "testname") != 0) {
		return false;
	}

	talloc_set_name(p1, "%s", "testname");
	name = talloc_get_name(p1);
	talloc_free_children(p1);
	/* check its still a valid talloc ptr */
	talloc_get_size(talloc_get_name(p1));
	torture_assert("name", name == talloc_get_name(p1), "name ptr changed");
	torture_assert("namecheck", strcmp(talloc_get_name(p1), "testname") == 0,
		       "wrong name");
	CHECK_BLOCKS("name1", p1, 2);

	/* note that this does not free the old child name */
	talloc_set_name_const(p1, "testname2");
	name2 = talloc_get_name(p1);
	/* but this does */
	talloc_free_children(p1);
	torture_assert("namecheck", strcmp(talloc_get_name(p1), "testname2") == 0,
		       "wrong name");
	CHECK_BLOCKS("name1", p1, 1);

	talloc_report_full(root, stdout);
	talloc_free(root);
	return true;
}
Example #26
0
int main(int argc, char **argv)
{
	int quit = 0;
	int rc;
	char const * home;
	size_t len;
	const char osmocomcfg[] = ".osmocom/bb/mobile.cfg";
	char *config_file = NULL;

	printf("%s\n", openbsc_copyright);

	srand(time(NULL));

	INIT_LLIST_HEAD(&ms_list);
	log_init(&log_info, NULL);
	stderr_target = log_target_create_stderr();
	log_add_target(stderr_target);
	log_set_all_filter(stderr_target, 1);

	l23_ctx = talloc_named_const(NULL, 1, "layer2 context");
	msgb_set_talloc_ctx(l23_ctx);

	handle_options(argc, argv);

	if (!debug_set)
		log_parse_category_mask(stderr_target, debug_default);
	log_set_log_level(stderr_target, LOGL_DEBUG);

	if (gsmtap_ip) {
		gsmtap_inst = gsmtap_source_init(gsmtap_ip, GSMTAP_UDP_PORT, 1);
		if (!gsmtap_inst) {
			fprintf(stderr, "Failed during gsmtap_init()\n");
			exit(1);
		}
		gsmtap_source_add_sink(gsmtap_inst);
	}

	home = getenv("HOME");
	if (home != NULL) {
		len = strlen(home) + 1 + sizeof(osmocomcfg);
		config_file = talloc_size(l23_ctx, len);
		if (config_file != NULL)
			snprintf(config_file, len, "%s/%s", home, osmocomcfg);
	}
	/* save the config file directory name */
	config_dir = talloc_strdup(l23_ctx, config_file);
	config_dir = dirname(config_dir);

	if (use_mncc_sock)
		rc = l23_app_init(mncc_recv_socket, config_file, vty_port);
	else
		rc = l23_app_init(NULL, config_file, vty_port);
	if (rc)
		exit(rc);

	signal(SIGINT, sighandler);
	signal(SIGHUP, sighandler);
	signal(SIGTERM, sighandler);
	signal(SIGPIPE, sighandler);
	signal(SIGABRT, sighandler);
	signal(SIGUSR1, sighandler);
	signal(SIGUSR2, sighandler);

	if (daemonize) {
		printf("Running as daemon\n");
		rc = osmo_daemonize();
		if (rc)
			fprintf(stderr, "Failed to run as daemon\n");
	}

	while (1) {
		l23_app_work(&quit);
		if (quit && llist_empty(&ms_list))
			break;
		osmo_select_main(0);
	}

	l23_app_exit();

	talloc_free(config_file);
	talloc_free(config_dir);
	talloc_report_full(l23_ctx, stderr);

	return 0;
}
Example #27
0
/*
  miscellaneous tests to try to get a higher test coverage percentage
*/
static bool test_misc(void)
{
	void *root, *p1;
	char *p2;
	double *d;
	const char *name;

	printf("test: misc\n# MISCELLANEOUS\n");

	root = talloc_new(NULL);

	p1 = talloc_size(root, 0x7fffffff);
	torture_assert("misc", !p1, "failed: large talloc allowed\n");

	p1 = talloc_strdup(root, "foo");
	talloc_increase_ref_count(p1);
	talloc_increase_ref_count(p1);
	talloc_increase_ref_count(p1);
	CHECK_BLOCKS("misc", p1, 1);
	CHECK_BLOCKS("misc", root, 2);
	talloc_unlink(NULL, p1);
	CHECK_BLOCKS("misc", p1, 1);
	CHECK_BLOCKS("misc", root, 2);
	talloc_unlink(NULL, p1);
	CHECK_BLOCKS("misc", p1, 1);
	CHECK_BLOCKS("misc", root, 2);
	p2 = talloc_strdup(p1, "foo");
	torture_assert("misc", talloc_unlink(root, p2) == -1,
				   "failed: talloc_unlink() of non-reference context should return -1\n");
	torture_assert("misc", talloc_unlink(p1, p2) == 0,
		"failed: talloc_unlink() of parent should succeed\n");
	talloc_unlink(NULL, p1);
	CHECK_BLOCKS("misc", p1, 1);
	CHECK_BLOCKS("misc", root, 2);

	name = talloc_set_name(p1, "my name is %s", "foo");
	torture_assert_str_equal("misc", talloc_get_name(p1), "my name is foo",
		"failed: wrong name after talloc_set_name(my name is foo)");
	torture_assert_str_equal("misc", talloc_get_name(p1), name,
		"failed: wrong name after talloc_set_name(my name is foo)");
	CHECK_BLOCKS("misc", p1, 2);
	CHECK_BLOCKS("misc", root, 3);

	talloc_set_name_const(p1, NULL);
	torture_assert_str_equal ("misc", talloc_get_name(p1), "UNNAMED",
		"failed: wrong name after talloc_set_name(NULL)");
	CHECK_BLOCKS("misc", p1, 2);
	CHECK_BLOCKS("misc", root, 3);

	torture_assert("misc", talloc_free(NULL) == -1, 
				   "talloc_free(NULL) should give -1\n");

	talloc_set_destructor(p1, fail_destructor);
	torture_assert("misc", talloc_free(p1) == -1, 
		"Failed destructor should cause talloc_free to fail\n");
	talloc_set_destructor(p1, NULL);

	talloc_report(root, stderr);


	p2 = (char *)talloc_zero_size(p1, 20);
	torture_assert("misc", p2[19] == 0, "Failed to give zero memory\n");
	talloc_free(p2);

	torture_assert("misc", talloc_strdup(root, NULL) == NULL,
		"failed: strdup on NULL should give NULL\n");

	p2 = talloc_strndup(p1, "foo", 2);
	torture_assert("misc", strcmp("fo", p2) == 0, 
				   "strndup doesn't work\n");
	p2 = talloc_asprintf_append_buffer(p2, "o%c", 'd');
	torture_assert("misc", strcmp("food", p2) == 0, 
				   "talloc_asprintf_append_buffer doesn't work\n");
	CHECK_BLOCKS("misc", p2, 1);
	CHECK_BLOCKS("misc", p1, 3);

	p2 = talloc_asprintf_append_buffer(NULL, "hello %s", "world");
	torture_assert("misc", strcmp("hello world", p2) == 0,
		"talloc_asprintf_append_buffer doesn't work\n");
	CHECK_BLOCKS("misc", p2, 1);
	CHECK_BLOCKS("misc", p1, 3);
	talloc_free(p2);

	d = talloc_array(p1, double, 0x20000000);
	torture_assert("misc", !d, "failed: integer overflow not detected\n");

	d = talloc_realloc(p1, d, double, 0x20000000);
	torture_assert("misc", !d, "failed: integer overflow not detected\n");

	talloc_free(p1);
	CHECK_BLOCKS("misc", root, 1);

	p1 = talloc_named(root, 100, "%d bytes", 100);
	CHECK_BLOCKS("misc", p1, 2);
	CHECK_BLOCKS("misc", root, 3);
	talloc_unlink(root, p1);

	p1 = talloc_init("%d bytes", 200);
	p2 = talloc_asprintf(p1, "my test '%s'", "string");
	torture_assert_str_equal("misc", p2, "my test 'string'",
		"failed: talloc_asprintf(\"my test '%%s'\", \"string\") gave: \"%s\"");
	CHECK_BLOCKS("misc", p1, 3);
	CHECK_SIZE("misc", p2, 17);
	CHECK_BLOCKS("misc", root, 1);
	talloc_unlink(NULL, p1);

	p1 = talloc_named_const(root, 10, "p1");
	p2 = (char *)talloc_named_const(root, 20, "p2");
	(void)talloc_reference(p1, p2);
	talloc_report_full(root, stderr);
	talloc_unlink(root, p2);
	talloc_report_full(root, stderr);
	CHECK_BLOCKS("misc", p2, 1);
	CHECK_BLOCKS("misc", p1, 2);
	CHECK_BLOCKS("misc", root, 3);
	talloc_unlink(p1, p2);
	talloc_unlink(root, p1);

	p1 = talloc_named_const(root, 10, "p1");
	p2 = (char *)talloc_named_const(root, 20, "p2");
	(void)talloc_reference(NULL, p2);
	talloc_report_full(root, stderr);
	talloc_unlink(root, p2);
	talloc_report_full(root, stderr);
	CHECK_BLOCKS("misc", p2, 1);
	CHECK_BLOCKS("misc", p1, 1);
	CHECK_BLOCKS("misc", root, 2);
	talloc_unlink(NULL, p2);
	talloc_unlink(root, p1);

	/* Test that talloc_unlink is a no-op */

	torture_assert("misc", talloc_unlink(root, NULL) == -1,
		"failed: talloc_unlink(root, NULL) == -1\n");

	talloc_report(root, stderr);
	talloc_report(NULL, stderr);

	CHECK_SIZE("misc", root, 0);

	talloc_free(root);

	CHECK_SIZE("misc", NULL, 0);

	talloc_enable_null_tracking_no_autofree();
	talloc_enable_leak_report();
	talloc_enable_leak_report_full();

	printf("success: misc\n");

	return true;
}
Example #28
0
/* sec_mod_server:
 * @config: server configuration
 * @socket_file: the name of the socket
 * @cmd_fd: socket to exchange commands with main
 * @cmd_fd_sync: socket to received sync commands from main
 *
 * This is the main part of the security module.
 * It creates the unix domain socket identified by @socket_file
 * and then accepts connections from the workers to it. Then 
 * it serves commands requested on the server's private key.
 *
 * When the operation is decrypt the provided data are
 * decrypted and sent back to worker. The sign operation
 * signs the provided data.
 *
 * The security module's reply to the worker has the
 * following format:
 * byte[0-5]: length (uint32_t)
 * byte[5-total]: data (signature or decrypted data)
 *
 * The reason for having this as a separate process
 * is to avoid any bug on the workers to leak the key.
 * It is not part of main because workers are spawned
 * from main, and thus should be prevented from accessing
 * parts the key in stack or heap that was not zeroized.
 * Other than that it allows the main server to spawn
 * clients fast without becoming a bottleneck due to private 
 * key operations.
 */
void sec_mod_server(void *main_pool, struct perm_cfg_st *perm_config, const char *socket_file,
		    int cmd_fd, int cmd_fd_sync)
{
	struct sockaddr_un sa;
	socklen_t sa_len;
	int cfd, ret, e, n;
	unsigned buffer_size;
	uid_t uid;
	uint8_t *buffer;
	int sd;
	sec_mod_st *sec;
	void *sec_mod_pool;
	fd_set rd_set;
	pid_t pid;
#ifdef HAVE_PSELECT
	struct timespec ts;
#else
	struct timeval ts;
#endif
	sigset_t emptyset, blockset;

#ifdef DEBUG_LEAKS
	talloc_enable_leak_report_full();
#endif
	sigemptyset(&blockset);
	sigemptyset(&emptyset);
	sigaddset(&blockset, SIGALRM);
	sigaddset(&blockset, SIGTERM);
	sigaddset(&blockset, SIGINT);
	sigaddset(&blockset, SIGHUP);

	sec_mod_pool = talloc_init("sec-mod");
	if (sec_mod_pool == NULL) {
		seclog(sec, LOG_ERR, "error in memory allocation");
		exit(1);
	}

	sec = talloc_zero(sec_mod_pool, sec_mod_st);
	if (sec == NULL) {
		seclog(sec, LOG_ERR, "error in memory allocation");
		exit(1);
	}

	sec->perm_config = talloc_steal(sec, perm_config);
	sec->config = sec->perm_config->config;

	tls_cache_init(sec, &sec->tls_db);
	sup_config_init(sec);

	memset(&sa, 0, sizeof(sa));
	sa.sun_family = AF_UNIX;
	strlcpy(sa.sun_path, socket_file, sizeof(sa.sun_path));
	remove(socket_file);

#define SOCKET_FILE sa.sun_path

	/* we no longer need the main pool after this point. */
	talloc_free(main_pool);

	ocsignal(SIGHUP, handle_sighup);
	ocsignal(SIGINT, handle_sigterm);
	ocsignal(SIGTERM, handle_sigterm);
	ocsignal(SIGALRM, handle_alarm);

	sec_auth_init(sec, perm_config);
	sec->cmd_fd = cmd_fd;
	sec->cmd_fd_sync = cmd_fd_sync;

#ifdef HAVE_PKCS11
	ret = gnutls_pkcs11_reinit();
	if (ret < 0) {
		seclog(sec, LOG_WARNING, "error in PKCS #11 reinitialization: %s",
		       gnutls_strerror(ret));
	}
#endif

	if (sec_mod_client_db_init(sec) == NULL) {
		seclog(sec, LOG_ERR, "error in client db initialization");
		exit(1);
	}

	sd = socket(AF_UNIX, SOCK_STREAM, 0);
	if (sd == -1) {
		e = errno;
		seclog(sec, LOG_ERR, "could not create socket '%s': %s", SOCKET_FILE,
		       strerror(e));
		exit(1);
	}
	set_cloexec_flag(sd, 1);

	umask(066);
	ret = bind(sd, (struct sockaddr *)&sa, SUN_LEN(&sa));
	if (ret == -1) {
		e = errno;
		seclog(sec, LOG_ERR, "could not bind socket '%s': %s", SOCKET_FILE,
		       strerror(e));
		exit(1);
	}

	ret = chown(SOCKET_FILE, perm_config->uid, perm_config->gid);
	if (ret == -1) {
		e = errno;
		seclog(sec, LOG_INFO, "could not chown socket '%s': %s", SOCKET_FILE,
		       strerror(e));
	}

	ret = listen(sd, 1024);
	if (ret == -1) {
		e = errno;
		seclog(sec, LOG_ERR, "could not listen to socket '%s': %s",
		       SOCKET_FILE, strerror(e));
		exit(1);
	}

	ret = load_keys(sec, 1);
	if (ret < 0) {
		seclog(sec, LOG_ERR, "error loading private key files");
		exit(1);
	}

	sigprocmask(SIG_BLOCK, &blockset, &sig_default_set);
	alarm(MAINTAINANCE_TIME);
	seclog(sec, LOG_INFO, "sec-mod initialized (socket: %s)", SOCKET_FILE);


	for (;;) {
		check_other_work(sec);

		FD_ZERO(&rd_set);
		n = 0;

		FD_SET(cmd_fd, &rd_set);
		n = MAX(n, cmd_fd);

		FD_SET(cmd_fd_sync, &rd_set);
		n = MAX(n, cmd_fd_sync);

		FD_SET(sd, &rd_set);
		n = MAX(n, sd);

#ifdef HAVE_PSELECT
		ts.tv_nsec = 0;
		ts.tv_sec = 120;
		ret = pselect(n + 1, &rd_set, NULL, NULL, &ts, &emptyset);
#else
		ts.tv_usec = 0;
		ts.tv_sec = 120;
		sigprocmask(SIG_UNBLOCK, &blockset, NULL);
		ret = select(n + 1, &rd_set, NULL, NULL, &ts);
		sigprocmask(SIG_BLOCK, &blockset, NULL);
#endif
		if (ret == 0 || (ret == -1 && errno == EINTR))
			continue;

		if (ret < 0) {
			e = errno;
			seclog(sec, LOG_ERR, "Error in pselect(): %s",
			       strerror(e));
			exit(1);
		}

		/* we do a new allocation, to also use it as pool for the
		 * parsers to use */
		buffer_size = MAX_MSG_SIZE;
		buffer = talloc_size(sec, buffer_size);
		if (buffer == NULL) {
			seclog(sec, LOG_ERR, "error in memory allocation");
			exit(1);
		}

		/* we use two fds for communication with main. The synchronous is for
		 * ping-pong communication which each request is answered immediated. The
		 * async is for messages sent back and forth in no particular order */
		if (FD_ISSET(cmd_fd_sync, &rd_set)) {
			ret = serve_request_main(sec, cmd_fd_sync, buffer, buffer_size);
			if (ret < 0 && ret == ERR_BAD_COMMAND) {
				seclog(sec, LOG_ERR, "error processing sync command from main");
				exit(1);
			}
		}

		if (FD_ISSET(cmd_fd, &rd_set)) {
			ret = serve_request_main(sec, cmd_fd, buffer, buffer_size);
			if (ret < 0 && ret == ERR_BAD_COMMAND) {
				seclog(sec, LOG_ERR, "error processing async command from main");
				exit(1);
			}
		}
		
		if (FD_ISSET(sd, &rd_set)) {
			sa_len = sizeof(sa);
			cfd = accept(sd, (struct sockaddr *)&sa, &sa_len);
			if (cfd == -1) {
				e = errno;
				if (e != EINTR) {
					seclog(sec, LOG_DEBUG,
					       "sec-mod error accepting connection: %s",
					       strerror(e));
					goto cont;
				}
			}
			set_cloexec_flag (cfd, 1);

			/* do not allow unauthorized processes to issue commands
			 */
			ret = check_upeer_id("sec-mod", sec->perm_config->debug, cfd, perm_config->uid, perm_config->gid, &uid, &pid);
			if (ret < 0) {
				seclog(sec, LOG_INFO, "rejected unauthorized connection");
			} else {
				memset(buffer, 0, buffer_size);
				serve_request_worker(sec, cfd, pid, buffer, buffer_size);
			}
			close(cfd);
		}
 cont:
		talloc_free(buffer);
#ifdef DEBUG_LEAKS
		talloc_report_full(sec, stderr);
#endif
	}
}
Example #29
0
int main(int argc, char *argv[])
{
	struct gprs_rlcmac_bts *bts;
	int rc;

	tall_pcu_ctx = talloc_named_const(NULL, 1, "Osmo-PCU context");
	if (!tall_pcu_ctx)
		return -ENOMEM;
	bv_tall_ctx = tall_pcu_ctx;

	bts = gprs_rlcmac_bts = talloc_zero(tall_pcu_ctx,
						struct gprs_rlcmac_bts);
	if (!gprs_rlcmac_bts)
		return -ENOMEM;
	bts->fc_interval = 1;
	bts->initial_cs_dl = bts->initial_cs_ul = 1;
	bts->cs1 = 1;
	bts->t3142 = 20;
	bts->t3169 = 5;
	bts->t3191 = 5;
	bts->t3193_msec = 100;
	bts->t3195 = 5;
	bts->n3101 = 10;
	bts->n3103 = 4;
	bts->n3105 = 8;
	bts->alpha = 0; /* a = 0.0 */

	msgb_set_talloc_ctx(tall_pcu_ctx);

	osmo_init_logging(&gprs_log_info);

	vty_init(&pcu_vty_info);
	pcu_vty_init(&gprs_log_info);

	handle_options(argc, argv);
	if ((!!spoof_mcc) + (!!spoof_mnc) == 1) {
		fprintf(stderr, "--mcc and --mnc must be specified "
			"together.\n");
		exit(0);
	}

	rc = vty_read_config_file(config_file, NULL);
	if (rc < 0 && config_given) {
		fprintf(stderr, "Failed to parse the config file: '%s'\n",
			config_file);
		exit(1);
	}
	if (rc < 0)
		fprintf(stderr, "No config file: '%s' Using default config.\n",
			config_file);

	rc = telnet_init(tall_pcu_ctx, NULL, 4240);
	if (rc < 0) {
		fprintf(stderr, "Error initializing telnet\n");
		exit(1);
	}

	if (!bts->alloc_algorithm)
		bts->alloc_algorithm = alloc_algorithm_b;

	rc = pcu_l1if_open();

	if (rc < 0)
		return rc;

	signal(SIGINT, sighandler);
	signal(SIGHUP, sighandler);
	signal(SIGTERM, sighandler);
	signal(SIGPIPE, sighandler);
	signal(SIGABRT, sighandler);
	signal(SIGUSR1, sighandler);
	signal(SIGUSR2, sighandler);

	while (!quit) {
		osmo_gsm_timers_check();
		osmo_gsm_timers_prepare();
		osmo_gsm_timers_update();

		osmo_select_main(0);
#ifdef DEBUG_DIAGRAM
		gettimeofday(&diagram_time, NULL);
#endif
	}

	telnet_exit();

	pcu_l1if_close();

	talloc_free(gprs_rlcmac_bts);

	talloc_report_full(tall_pcu_ctx, stderr);
	talloc_free(tall_pcu_ctx);

	return 0;
}
Example #30
0
int main(int argc, char *argv[])
{
	struct sched_param param;
	struct gprs_rlcmac_bts *bts;
	int rc;

	tall_pcu_ctx = talloc_named_const(NULL, 1, "Osmo-PCU context");
	if (!tall_pcu_ctx)
		return -ENOMEM;
	bv_tall_ctx = tall_pcu_ctx;

	bts = bts_main_data();
	bts->fc_interval = 1;
	bts->initial_cs_dl = bts->initial_cs_ul = 1;
	bts->cs1 = 1;
	bts->t3142 = 20;
	bts->t3169 = 5;
	bts->t3191 = 5;
	bts->t3193_msec = 100;
	bts->t3195 = 5;
	bts->n3101 = 10;
	bts->n3103 = 4;
	bts->n3105 = 8;
	bts->alpha = 0; /* a = 0.0 */

	msgb_set_talloc_ctx(tall_pcu_ctx);

	osmo_init_logging(&gprs_log_info);

	vty_init(&pcu_vty_info);
	pcu_vty_init(&gprs_log_info);

	handle_options(argc, argv);
	if ((!!spoof_mcc) + (!!spoof_mnc) == 1) {
		fprintf(stderr, "--mcc and --mnc must be specified "
			"together.\n");
		exit(0);
	}

	rc = vty_read_config_file(config_file, NULL);
	if (rc < 0 && config_given) {
		fprintf(stderr, "Failed to parse the config file: '%s'\n",
			config_file);
		exit(1);
	}
	if (rc < 0)
		fprintf(stderr, "No config file: '%s' Using default config.\n",
			config_file);

	rc = telnet_init(tall_pcu_ctx, NULL, 4240);
	if (rc < 0) {
		fprintf(stderr, "Error initializing telnet\n");
		exit(1);
	}

	if (!bts->alloc_algorithm)
		bts->alloc_algorithm = alloc_algorithm_b;

	rc = pcu_l1if_open();

	if (rc < 0)
		return rc;

	signal(SIGINT, sighandler);
	signal(SIGHUP, sighandler);
	signal(SIGTERM, sighandler);
	signal(SIGPIPE, sighandler);
	signal(SIGABRT, sighandler);
	signal(SIGUSR1, sighandler);
	signal(SIGUSR2, sighandler);

	/* enable realtime priority for us */
	if (rt_prio != -1) {
		memset(&param, 0, sizeof(param));
		param.sched_priority = rt_prio;
		rc = sched_setscheduler(getpid(), SCHED_RR, &param);
		if (rc != 0) {
			fprintf(stderr, "Setting SCHED_RR priority(%d) failed: %s\n",
			param.sched_priority, strerror(errno));
			exit(1);
		}
	}

	while (!quit) {
		osmo_gsm_timers_check();
		osmo_gsm_timers_prepare();
		osmo_gsm_timers_update();

		osmo_select_main(0);
	}

	telnet_exit();

	pcu_l1if_close();

	bts->bts->timing_advance()->flush();

	talloc_report_full(tall_pcu_ctx, stderr);
	talloc_free(tall_pcu_ctx);

	return 0;
}