You’ve been waiting long enough!
In my previous post on the problems with a polling waitfor, I mentioned that there was a timing window in which we could miss the notification event.
If the path we were looking for was attached in between the stat() and the procmgr_event_notify() call (admittedly a small window) then we would end up waiting the entire timeout duration before noticing that the path had appeared.
Here’s a new version that uses a pulse that closes that hole, by using a pulse as the notification event.
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <time.h>
#include <sys/netmgr.h>
#include <sys/neutrino.h>
#include <sys/procmgr.h>
#include <sys/siginfo.h>
#define PULSE_CODE_TIMEOUT _PULSE_CODE_MINAVAIL
#define PULSE_CODE_PATHSPACE PULSE_CODE_TIMEOUT+1
int main( int argc, char *argv[] )
{
struct itimerspec timeout;
int timer_id;
struct sigevent event;
struct stat sbuf;
int chid, coid;
char *path;
struct _pulse pulse;
path = argv[1];
memset( &timeout, 0, sizeof(timeout) );
timeout.it_value.tv_sec = atoi(argv[2]);
chid = ChannelCreate(0);
coid = ConnectAttach( ND_LOCAL_NODE, 0, chid, _NTO_SIDE_CHANNEL, 0 );
SIGEV_PULSE_INIT( &event, coid, getprio(0), PULSE_CODE_TIMEOUT, 0 );
timer_create( CLOCK_REALTIME, &event, &timer_id );
/* make sure PATHSPACE event has higher priority */
SIGEV_PULSE_INIT( &event, coid, getprio(0)+1, PULSE_CODE_PATHSPACE, 0 );
procmgr_event_notify( PROCMGR_EVENT_PATHSPACE, &event );
/* Check to make sure we don't wait for something already there... */
if ( stat( argv[1], &sbuf ) == 0 ) {
printf("Found %s\\n", path );
return EXIT_SUCCESS;
}
timer_settime( timer_id, 0, &timeout, NULL );
while( MsgReceivePulse( chid, &pulse, sizeof(pulse), NULL ) == 0 ) {
switch(pulse.code) {
case PULSE_CODE_PATHSPACE:
if ( stat( argv[1], &sbuf ) == 0 ) {
printf("Found %s\\n", path );
return EXIT_SUCCESS;
}
break;
case PULSE_CODE_TIMEOUT:
printf("Timed out waiting for %s\\n", path);
return EXIT_FAILURE;
default:
printf("Unknown pulse code %d waiting for %s\\n", pulse.code, path);
return EXIT_FAILURE;
}
}
return EXIT_FAILURE;
}
Note that I use a timeout pulse too, and make the timeout pulse have a lower priority than the notification pulse. This is because pulses queue in priority order, and I want to make sure that I receive the path event pulse first.
Cheers,
Colin
Comments(2)