Stopping msieve before completion

I was in the situation recently where I was using msieve to factor large integers and wanted msieve to stop factoring after a certain time even if it had not completed the factorisation. msieve itself does not provide a way of doing this but the demo.c program that comes with msieve contains a method by which it can be done. The method involves threading and signalling.

The first step is to create a thread in which a timer is started. I created the thread just before the factoring was about to start by adding this code to that part of the program. The variable deadline provides the length of time for which the timer should run before sending a signal.

int32 deadline = 1;
pthread_t thread_id;
pthread_create(&thread_id, NULL, countdown_thread, &deadline);

The thread (called countdown_thread) raises a signal (the user defined signal SIGUSR1) when the timer has finished.

void *countdown_thread(void *pminutes) {
	uint32 minutes = *(uint32 *)pminutes;
	if (minutes > 0xffffffff / 60)
		minutes = 0xffffffff / 60;   // infinite
	sleep(minutes * 60);
	raise(SIGUSR1);
	return NULL;
}

How does the program know what to do when SIGUSR1 is raised? This is set up by adding these lines prior to starting the thread.

if (signal(SIGUSR1, handle_signal) == SIG_ERR) {
	printf("could not install handler on SIGUSR1\n");
	return;
}

The instruction signal(SIGUSR1, handle_signal) tells the program to invoke the function handle_signal when it receives the signal SIGUSR1. The handle_signal function stops msieve by setting the appropriate flag.

void handle_signal(int sig) {
	msieve_obj *obj = g_curr_factorization;
	if (obj && (obj->flags & MSIEVE_FLAG_SIEVING_IN_PROGRESS))
		obj->flags |= MSIEVE_FLAG_STOP_SIEVING;
	else
		return;
}

There was an obstacle to all this working. Unfortunately, the xcode compiler stops when it receives a signal and brings up the debugger. Thus the program does not continue executing. There is a way around this which seems a little strange. The solution involves creating a breakpoint in main.m at the line

return NSApplicationMain(argc, (const char **)argv);

You then edit the breakpoint, tick the options box (“Automatically continue after evaluating”) and add the Debugger Command
process handle SIGUSR1 -n true -p true -s false
I found the solution on stackoverflow at
http://stackoverflow.com/questions/10431579/permanently-configuring-lldb-in-xcode-4-3-2-not-to-stop-on-signals
One final thing to do is to update the display to show that factorisation was interrupted before completion. This is done by passing the relevant NSMutableString and NSTextView objects to the factoring function (via myString and myView) and then adding these lines after the msieve_run line.

if (!(g_curr_factorization->flags & MSIEVE_FLAG_FACTORIZATION_DONE)) {
	[myString appendString:@"factorisation was aborted due to time constraints"];
	[myView setString:myString];
	return;
}
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: