Code:
#include "dlist.h"
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
#include <sys/wait.h>
#include <pthread.h>
#include <time.h>
#define MAXTIMES 300
long dlist_count;
struct _encap_ {
int timer;
};
void *interrupt_hup(void *val) {
struct _encap_ p;
time_t now, then;
pthread_detach(pthread_self());
memcpy(&p,val,sizeof(p));
printf("Interval set at %d\nThread id %d waiting till %d -- now = %d\n",p.timer,pthread_self(),time(NULL) + p.timer,time(NULL));
then = now = time(NULL);
while ((then = time(NULL)) < (now + p.timer)) {sleep(1);}
kill(getpid(),SIGHUP);
pthread_exit(NULL);
}
void walk_dlist(DLIST * h)
{
int x = 0;
while (h != NULL) {
printf("Node %d at %p with prv = %p, nxt = %p and data = %p\n", x,
h, h->prv, h->nxt, h->data);
x++;
h = h->nxt;
}
}
void bwalk_list(DLIST * h, int place)
{
while (h != NULL) {
printf("Node %d at %p with prv = %p, nxt = %p and data = %p\n",
place, h, h->prv, h->nxt, h->data);
place--;
h = h->prv;
}
}
#define BSZ 256
/*idea create two separate dlists and keep them synched with pipes from parent to child
1) Allocate and populate pipe from stdin/file in parent. Create pipe. Close read end.
2) Create signal handler in parent for sighup and on receipt update the child list.
3) sigsuspend event loop
***child***
1) fork() and destroy the original dlist copy via dlist_destroy. Close write end of pipe.
2) Create list head and then event loop -- block on read from pipe and add to list with inbound data.
*/
DLIST *global;
int pip[2];
void handlehup(int sig) {
int v = 0;
char *dta;
while (v < dlist_count) {
dta = (dlist_element(global,v))->data;
if (dta != NULL) {write(pip[1],dta,strlen(dta));}
v++;
}
printf("Finished update...\n");
}
int do_child(void) {
int ret;
pid_t cn;
char buf[BSZ];
char *rec;
DLIST *synchrony;
sigset_t mask;
if ( (cn = fork()) == 0) {
sigemptyset(&mask);
sigprocmask(SIG_SETMASK,&mask,NULL);
close(pip[1]);
dlist_destroy(global,free);
synchrony = dlist_element_init(NULL);
bzero(buf,BSZ);
while ((ret = read(pip[0],buf,BSZ)) > 0) {
rec = malloc(BSZ);
strcpy(rec,buf);
dlist_append(synchrony,dlist_element_init(&rec));
printf("Received new record in list at %p with %d elements = \n%s\n at pid %d\n",synchrony,dlist_count,rec,getpid());
}
printf("Exiting due to pipe read error in %d with return = %d\n",getpid(),ret);
perror("read()");
walk_dlist(synchrony);
if (dlist_count > 0) {dlist_destroy(synchrony,free);}
exit(1);
} else {
return cn;
}
}
int main(int argc, char **argv) {
int x;
FILE *pt;
char buf[BSZ];
char *rec;
pid_t chld;
struct _encap_ f;
sigset_t mask;
pthread_t interrupto;
if (argc != 2) {printf("Error: Please specify file for information in list.\n"); return -1;}
if ( (pt = fopen(argv[1],"r")) == NULL) {perror("fopen()"); return -1;}
signal(SIGHUP,handlehup);
global = dlist_element_init(NULL);
srand(time(NULL));
bzero(buf,BSZ);
while (fgets(buf,BSZ,pt) != NULL) {
rec = malloc(BSZ);
strcpy(rec,buf);
dlist_append(global,dlist_element_init(&rec));
}
walk_dlist(global);
pipe(pip);
sigfillset(&mask);
sigdelset(&mask,SIGHUP);
sigdelset(&mask,SIGINT);
sigdelset(&mask,SIGCHLD);
printf("Starting child process at %d\n",chld = do_child());
close(pip[0]);
while (1) {f.timer = (1 + rand() % MAXTIMES); pthread_create(&interrupto,NULL,interrupt_hup,&f); sigsuspend(&mask); waitpid(0,NULL,WNOHANG);}
return 1;
}