From cb9c37fbd15a9469bee81c1293e8c73ecfae8d1c Mon Sep 17 00:00:00 2001 From: eddyem Date: Wed, 11 Nov 2015 19:56:59 +0300 Subject: [PATCH] add FITS. --- FITS/Makefile | 22 +++ FITS/README | 1 + FITS/fits.c | 161 +++++++++++++++++++++ FITS/fits.h | 42 ++++++ FITS/main.c | 44 ++++++ FITS/usefull_macros.c | 327 ++++++++++++++++++++++++++++++++++++++++++ FITS/usefull_macros.h | 124 ++++++++++++++++ guard.c | 69 +++++++++ sigtest.c | 45 ++++++ 9 files changed, 835 insertions(+) create mode 100644 FITS/Makefile create mode 100644 FITS/README create mode 100644 FITS/fits.c create mode 100644 FITS/fits.h create mode 100644 FITS/main.c create mode 100644 FITS/usefull_macros.c create mode 100644 FITS/usefull_macros.h create mode 100644 guard.c create mode 100644 sigtest.c diff --git a/FITS/Makefile b/FITS/Makefile new file mode 100644 index 0000000..4d7286a --- /dev/null +++ b/FITS/Makefile @@ -0,0 +1,22 @@ +PROGRAM = fitsread +LDFLAGS = -lcfitsio +SRCS = $(wildcard *.c) +CC = gcc +DEFINES = -D_XOPEN_SOURCE=1111 -DEBUG +CXX = gcc +CFLAGS = -Wall -Werror -Wextra $(DEFINES) +OBJS = $(SRCS:.c=.o) +all : $(PROGRAM) +$(PROGRAM) : $(OBJS) + $(CC) $(CFLAGS) $(OBJS) $(LDFLAGS) -o $(PROGRAM) + +# some addition dependencies +# %.o: %.c +# $(CC) $(LDFLAGS) $(CFLAGS) $< -o $@ +#$(SRCS) : %.c : %.h $(INDEPENDENT_HEADERS) +# @touch $@ + +clean: + /bin/rm -f *.o *~ +depend: + $(CXX) -MM $(CXX.SRCS) diff --git a/FITS/README b/FITS/README new file mode 100644 index 0000000..f477a99 --- /dev/null +++ b/FITS/README @@ -0,0 +1 @@ +Simple routines for FITS reading/writing diff --git a/FITS/fits.c b/FITS/fits.c new file mode 100644 index 0000000..607b055 --- /dev/null +++ b/FITS/fits.c @@ -0,0 +1,161 @@ +/* + * fits.c - cfitsio routines + * + * Copyright 2015 Edward V. Emelianov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include +#include +#include + +#include "fits.h" +#include "usefull_macros.h" + +static int fitsstatus = 0; + +/* + * Macros for error processing when working with cfitsio functions + */ +#define TRYFITS(f, ...) \ +do{ fitsstatus = 0; \ + f(__VA_ARGS__, &fitsstatus); \ + if(fitsstatus){ \ + fits_report_error(stderr, fitsstatus); \ + return FALSE;} \ +}while(0) +#define FITSFUN(f, ...) \ +do{ fitsstatus = 0; \ + int ret = f(__VA_ARGS__, &fitsstatus); \ + if(ret || fitsstatus) \ + fits_report_error(stderr, fitsstatus); \ +}while(0) +#define WRITEKEY(...) \ +do{ fitsstatus = 0; \ + fits_write_key(__VA_ARGS__, &fitsstatus); \ + if(status) fits_report_error(stderr, status);\ +}while(0) + +void imfree(IMAGE **img){ + size_t i, sz = (*img)->keynum; + char **list = (*img)->keylist; + for(i = 0; i < sz; ++i) FREE(list[i]); + FREE((*img)->keylist); + FREE((*img)->data); + FREE(*img); +} + +bool readFITS(char *filename, IMAGE **fits){ + FNAME(); + bool ret = TRUE; + fitsfile *fp; +// float nullval = 0., imBits, bZero = 0., bScale = 1.; + int i, j, hdunum, hdutype, nkeys, keypos; + int naxis; + long naxes[2]; + char card[FLEN_CARD]; + IMAGE *img = MALLOC(IMAGE, 1); + + TRYFITS(fits_open_file, &fp, filename, READONLY); + FITSFUN(fits_get_num_hdus, fp, &hdunum); + if(hdunum < 1){ + WARNX(_("Can't read HDU")); + ret = FALSE; + goto returning; + } + // get image dimensions + TRYFITS(fits_get_img_param, fp, 2, &img->dtype, &naxis, naxes); + if(naxis > 2){ + WARNX(_("Images with > 2 dimensions are not supported")); + ret = FALSE; + goto returning; + } + img->width = naxes[0]; + img->height = naxes[1]; + DBG("got image %ldx%ld pix, bitpix=%d", naxes[0], naxes[1], img->dtype); + // loop through all HDUs + for(i = 1; !(fits_movabs_hdu(fp, i, &hdutype, &fitsstatus)); ++i){ + TRYFITS(fits_get_hdrpos, fp, &nkeys, &keypos); + int oldnkeys = img->keynum; + img->keynum += nkeys; + if(!(img->keylist = realloc(img->keylist, sizeof(char*) * img->keynum))){ + ERR(_("Can't realloc")); + } + char **currec = &(img->keylist[oldnkeys]); + DBG("HDU # %d of %d keys", i, nkeys); + for(j = 1; j <= nkeys; ++j){ + FITSFUN(fits_read_record, fp, j, card); + if(!fitsstatus){ + *currec = MALLOC(char, FLEN_CARD); + memcpy(*currec, card, FLEN_CARD); + DBG("key %d: %s", oldnkeys + j, *currec); + ++currec; + } + } + } + if(fitsstatus == END_OF_FILE){ + fitsstatus = 0; + }else{ + fits_report_error(stderr, fitsstatus); + ret = FALSE; + goto returning; + } + size_t sz = naxes[0] * naxes[1]; + img->data = MALLOC(double, sz); + int stat = 0; + TRYFITS(fits_read_img, fp, TDOUBLE, 1, sz, NULL, img->data, &stat); + if(stat) WARNX(_("Found %d pixels with undefined value"), stat); + DBG("ready"); + +returning: + FITSFUN(fits_close_file, fp); + if(!ret){ + imfree(&img); + } + if(fits) *fits = img; + return ret; +} + +bool writeFITS(char *filename, IMAGE *fits){ + int w = fits->width, h = fits->height; + long naxes[2] = {w, h}; + size_t sz = w * h, keys = fits->keynum; + fitsfile *fp; + + TRYFITS(fits_create_file, &fp, filename); + TRYFITS(fits_create_img, fp, fits->dtype, 2, naxes); + + if(keys){ // there's keys + size_t i; + char **records = fits->keylist; + for(i = 0; i < keys; ++i){ + char *rec = records[i]; + if(strncmp(rec, "SIMPLE", 6) == 0 || strncmp(rec, "EXTEND", 6) == 0) // key "file does conform ..." + continue; + else if(strncmp(rec, "COMMENT", 7) == 0) // comment of obligatory key in FITS head + continue; + else if(strncmp(rec, "NAXIS", 5) == 0 || strncmp(rec, "BITPIX", 6) == 0) // NAXIS, NAXISxxx, BITPIX + continue; + FITSFUN(fits_write_record, fp, rec); + } + } + FITSFUN(fits_write_record, fp, "COMMENT modified by simple test routine"); + + TRYFITS(fits_write_img, fp, TDOUBLE, 1, sz, fits->data); + TRYFITS(fits_close_file, fp); + return TRUE; +} diff --git a/FITS/fits.h b/FITS/fits.h new file mode 100644 index 0000000..46da3a7 --- /dev/null +++ b/FITS/fits.h @@ -0,0 +1,42 @@ +/* + * fits.h + * + * Copyright 2015 Edward V. Emelianov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +#pragma once +#ifndef __FITS_H__ +#define __FITS_H__ + +#include +#include + + +typedef struct{ + int width; // width + int height; // height + int dtype; // data type + double *data; // picture data + char **keylist; // list of options for each key + size_t keynum; // full number of keys (size of *keylist) +} IMAGE; + +void imfree(IMAGE **ima); +bool readFITS(char *filename, IMAGE **fits); +bool writeFITS(char *filename, IMAGE *fits); + +#endif // __FITS_H__ diff --git a/FITS/main.c b/FITS/main.c new file mode 100644 index 0000000..68ba979 --- /dev/null +++ b/FITS/main.c @@ -0,0 +1,44 @@ +/* + * main.c + * + * Copyright 2015 Edward V. Emelianov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include +#include "usefull_macros.h" +#include "fits.h" + +void signals(int signo){ + exit(signo); +} + +int main(int argc, char **argv){ + IMAGE *fits; + //size_t i, s; + initial_setup(); + if(argc != 3) ERRX("Usage: %s infile outfile", argv[0]); + readFITS(argv[1], &fits); + DBG("ima: %dx%d", fits->width, fits->height); + //s = fits->width * fits->height; + //double *img = fits->data; + //for(i = 0; i < s; ++i) *img++ /= 2.; + unlink(argv[2]); + writeFITS(argv[2], fits); + imfree(&fits); + return 0; +} diff --git a/FITS/usefull_macros.c b/FITS/usefull_macros.c new file mode 100644 index 0000000..f97c181 --- /dev/null +++ b/FITS/usefull_macros.c @@ -0,0 +1,327 @@ +/* + * usefull_macros.h - a set of usefull functions: memory, color etc + * + * Copyright 2013 Edward V. Emelianoff + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include "usefull_macros.h" + +/** + * function for different purposes that need to know time intervals + * @return double value: time in seconds + */ +double dtime(){ + double t; + struct timeval tv; + gettimeofday(&tv, NULL); + t = tv.tv_sec + ((double)tv.tv_usec)/1e6; + return t; +} + +/******************************************************************************\ + * Coloured terminal +\******************************************************************************/ +int globErr = 0; // errno for WARN/ERR + +// pointers to coloured output printf +int (*red)(const char *fmt, ...); +int (*green)(const char *fmt, ...); +int (*_WARN)(const char *fmt, ...); + +/* + * format red / green messages + * name: r_pr_, g_pr_ + * @param fmt ... - printf-like format + * @return number of printed symbols + */ +int r_pr_(const char *fmt, ...){ + va_list ar; int i; + printf(RED); + va_start(ar, fmt); + i = vprintf(fmt, ar); + va_end(ar); + printf(OLDCOLOR); + return i; +} +int g_pr_(const char *fmt, ...){ + va_list ar; int i; + printf(GREEN); + va_start(ar, fmt); + i = vprintf(fmt, ar); + va_end(ar); + printf(OLDCOLOR); + return i; +} +/* + * print red error/warning messages (if output is a tty) + * @param fmt ... - printf-like format + * @return number of printed symbols + */ +int r_WARN(const char *fmt, ...){ + va_list ar; int i = 1; + fprintf(stderr, RED); + va_start(ar, fmt); + if(globErr){ + errno = globErr; + vwarn(fmt, ar); + errno = 0; + globErr = 0; + }else + i = vfprintf(stderr, fmt, ar); + va_end(ar); + i++; + fprintf(stderr, OLDCOLOR "\n"); + return i; +} + +static const char stars[] = "****************************************"; +/* + * notty variants of coloured printf + * name: s_WARN, r_pr_notty + * @param fmt ... - printf-like format + * @return number of printed symbols + */ +int s_WARN(const char *fmt, ...){ + va_list ar; int i; + i = fprintf(stderr, "\n%s\n", stars); + va_start(ar, fmt); + if(globErr){ + errno = globErr; + vwarn(fmt, ar); + errno = 0; + globErr = 0; + }else + i = +vfprintf(stderr, fmt, ar); + va_end(ar); + i += fprintf(stderr, "\n%s\n", stars); + i += fprintf(stderr, "\n"); + return i; +} +int r_pr_notty(const char *fmt, ...){ + va_list ar; int i; + i = printf("\n%s\n", stars); + va_start(ar, fmt); + i += vprintf(fmt, ar); + va_end(ar); + i += printf("\n%s\n", stars); + return i; +} + +/** + * Run this function in the beginning of main() to setup locale & coloured output + */ +void initial_setup(){ + // setup coloured output + if(isatty(STDOUT_FILENO)){ // make color output in tty + red = r_pr_; green = g_pr_; + }else{ // no colors in case of pipe + red = r_pr_notty; green = printf; + } + if(isatty(STDERR_FILENO)) _WARN = r_WARN; + else _WARN = s_WARN; + // Setup locale + setlocale(LC_ALL, ""); + setlocale(LC_NUMERIC, "C"); +#if defined GETTEXT_PACKAGE && defined LOCALEDIR + bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR); + textdomain(GETTEXT_PACKAGE); +#endif +} + +/******************************************************************************\ + * Memory +\******************************************************************************/ +/* + * safe memory allocation for macro ALLOC + * @param N - number of elements to allocate + * @param S - size of single element (typically sizeof) + * @return pointer to allocated memory area + */ +void *my_alloc(size_t N, size_t S){ + void *p = calloc(N, S); + if(!p) ERR("malloc"); + //assert(p); + return p; +} + +/** + * Mmap file to a memory area + * + * @param filename (i) - name of file to mmap + * @return stuct with mmap'ed file or die + */ +mmapbuf *My_mmap(char *filename){ + int fd; + char *ptr; + size_t Mlen; + struct stat statbuf; + if(!filename) ERRX(_("No filename given!")); + if((fd = open(filename, O_RDONLY)) < 0) + ERR(_("Can't open %s for reading"), filename); + if(fstat (fd, &statbuf) < 0) + ERR(_("Can't stat %s"), filename); + Mlen = statbuf.st_size; + if((ptr = mmap (0, Mlen, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED) + ERR(_("Mmap error for input")); + if(close(fd)) ERR(_("Can't close mmap'ed file")); + mmapbuf *ret = MALLOC(mmapbuf, 1); + ret->data = ptr; + ret->len = Mlen; + return ret; +} + +void My_munmap(mmapbuf *b){ + if(munmap(b->data, b->len)) + ERR(_("Can't munmap")); + FREE(b); +} + + +/******************************************************************************\ + * Terminal in no-echo mode +\******************************************************************************/ +static struct termios oldt, newt; // terminal flags +static int console_changed = 0; +// run on exit: +void restore_console(){ + if(console_changed) + tcsetattr(STDIN_FILENO, TCSANOW, &oldt); // return terminal to previous state + console_changed = 0; +} + +// initial setup: +void setup_con(){ + if(console_changed) return; + tcgetattr(STDIN_FILENO, &oldt); + newt = oldt; + newt.c_lflag &= ~(ICANON | ECHO); + if(tcsetattr(STDIN_FILENO, TCSANOW, &newt) < 0){ + WARN(_("Can't setup console")); + tcsetattr(STDIN_FILENO, TCSANOW, &oldt); + signals(0); //quit? + } + console_changed = 1; +} + +/** + * Read character from console without echo + * @return char readed + */ +int read_console(){ + int rb; + struct timeval tv; + int retval; + fd_set rfds; + FD_ZERO(&rfds); + FD_SET(STDIN_FILENO, &rfds); + tv.tv_sec = 0; tv.tv_usec = 10000; + retval = select(1, &rfds, NULL, NULL, &tv); + if(!retval) rb = 0; + else { + if(FD_ISSET(STDIN_FILENO, &rfds)) rb = getchar(); + else rb = 0; + } + return rb; +} + +/** + * getchar() without echo + * wait until at least one character pressed + * @return character readed + */ +int mygetchar(){ // getchar() without need of pressing ENTER + int ret; + do ret = read_console(); + while(ret == 0); + return ret; +} + + +/******************************************************************************\ + * TTY with select() +\******************************************************************************/ +static struct termio oldtty, tty; // TTY flags +static int comfd = -1; // TTY fd + +// run on exit: +void restore_tty(){ + if(comfd == -1) return; + ioctl(comfd, TCSANOW, &oldtty ); // return TTY to previous state + close(comfd); + comfd = -1; +} + +#ifndef BAUD_RATE +#define BAUD_RATE B9600 +#endif +// init: +void tty_init(char *comdev){ + DBG("\nOpen port...\n"); + if ((comfd = open(comdev,O_RDWR|O_NOCTTY|O_NONBLOCK)) < 0){ + WARN("Can't use port %s\n",comdev); + ioctl(comfd, TCSANOW, &oldtty); // return TTY to previous state + close(comfd); + signals(0); // quit? + } + DBG(" OK\nGet current settings... "); + if(ioctl(comfd,TCGETA,&oldtty) < 0){ // Get settings + WARN(_("Can't get settings")); + signals(0); + } + tty = oldtty; + tty.c_lflag = 0; // ~(ICANON | ECHO | ECHOE | ISIG) + tty.c_oflag = 0; + tty.c_cflag = BAUD_RATE|CS8|CREAD|CLOCAL; // 9.6k, 8N1, RW, ignore line ctrl + tty.c_cc[VMIN] = 0; // non-canonical mode + tty.c_cc[VTIME] = 5; + if(ioctl(comfd,TCSETA,&tty) < 0){ + WARN(_("Can't set settings")); + signals(0); + } + DBG(" OK\n"); +} +/** + * Read data from TTY + * @param buff (o) - buffer for data read + * @param length - buffer len + * @return amount of readed bytes + */ +size_t read_tty(uint8_t *buff, size_t length){ + ssize_t L = 0; + fd_set rfds; + struct timeval tv; + int retval; + FD_ZERO(&rfds); + FD_SET(comfd, &rfds); + tv.tv_sec = 0; tv.tv_usec = 50000; // wait for 50ms + retval = select(comfd + 1, &rfds, NULL, NULL, &tv); + if (!retval) return 0; + if(FD_ISSET(comfd, &rfds)){ + if((L = read(comfd, buff, length)) < 1) return 0; + } + return (size_t)L; +} + +int write_tty(uint8_t *buff, size_t length){ + ssize_t L = write(comfd, buff, length); + if((size_t)L != length){ + WARN("Write error!"); + return 1; + } + return 0; +} diff --git a/FITS/usefull_macros.h b/FITS/usefull_macros.h new file mode 100644 index 0000000..bc000c2 --- /dev/null +++ b/FITS/usefull_macros.h @@ -0,0 +1,124 @@ +/* + * usefull_macros.h - a set of usefull macros: memory, color etc + * + * Copyright 2013 Edward V. Emelianoff + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#pragma once +#ifndef __USEFULL_MACROS_H__ +#define __USEFULL_MACROS_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined GETTEXT_PACKAGE && defined LOCALEDIR +/* + * GETTEXT + */ +#include +#define _(String) gettext(String) +#define gettext_noop(String) String +#define N_(String) gettext_noop(String) +#else +#define _(String) (String) +#define N_(String) (String) +#endif +#include +#include +#include +#include +#include +#include + + +// unused arguments with -Wall -Werror +#define _U_ __attribute__((__unused__)) + +/* + * Coloured messages output + */ +#define RED "\033[1;31;40m" +#define GREEN "\033[1;32;40m" +#define OLDCOLOR "\033[0;0;0m" + +/* + * ERROR/WARNING messages + */ +extern int globErr; +extern void signals(int sig); +#define ERR(...) do{globErr=errno; _WARN(__VA_ARGS__); signals(0);}while(0) +#define ERRX(...) do{globErr=0; _WARN(__VA_ARGS__); signals(0);}while(0) +#define WARN(...) do{globErr=errno; _WARN(__VA_ARGS__);}while(0) +#define WARNX(...) do{globErr=0; _WARN(__VA_ARGS__);}while(0) + +/* + * print function name, debug messages + * debug mode, -DEBUG + */ +#ifdef EBUG + #define FNAME() fprintf(stderr, "\n%s (%s, line %d)\n", __func__, __FILE__, __LINE__) + #define DBG(...) do{fprintf(stderr, "%s (%s, line %d): ", __func__, __FILE__, __LINE__); \ + fprintf(stderr, __VA_ARGS__); \ + fprintf(stderr, "\n");} while(0) +#else + #define FNAME() do{}while(0) + #define DBG(...) do{}while(0) +#endif //EBUG + +/* + * Memory allocation + */ +#define ALLOC(type, var, size) type * var = ((type *)my_alloc(size, sizeof(type))) +#define MALLOC(type, size) ((type *)my_alloc(size, sizeof(type))) +#define FREE(ptr) do{free(ptr); ptr = NULL;}while(0) + +double dtime(); + +// functions for color output in tty & no-color in pipes +extern int (*red)(const char *fmt, ...); +extern int (*_WARN)(const char *fmt, ...); +extern int (*green)(const char *fmt, ...); +void * my_alloc(size_t N, size_t S); +void initial_setup(); + +// mmap file +typedef struct{ + char *data; + size_t len; +} mmapbuf; +mmapbuf *My_mmap(char *filename); +void My_munmap(mmapbuf *b); + +void restore_console(); +void setup_con(); +int read_console(); +int mygetchar(); + +void restore_tty(); +void tty_init(char *comdev); +size_t read_tty(uint8_t *buff, size_t length); +int write_tty(uint8_t *buff, size_t length); + +#endif // __USEFULL_MACROS_H__ diff --git a/guard.c b/guard.c new file mode 100644 index 0000000..1fe3747 --- /dev/null +++ b/guard.c @@ -0,0 +1,69 @@ +#include +#include +#include +#include +#include +#include + +int child_killed = 0; +pthread_t athread; + +void sighndlr(int sig){ + printf("got signal %d\n", sig); + if(sig == SIGCHLD){ + printf("Child was killed\n"); + child_killed = 1; + }else if(sig == SIGSEGV){ + printf("suicide\n"); + pthread_exit(NULL); + }else + exit(sig); +} + +void dummy(){ + int i; + char *ptr = malloc(10000); + for(i = 0; i < 256; ++i, ptr += 1024){ + *ptr += i; + } +} + +pid_t create_child(){ + child_killed = 0; + pid_t p = fork(); + if(p == 0){ + printf("child\n"); + dummy(); + } + return p; +} + +void *thrfnctn(void *buf){ + dummy(); +} + +int main(){ + int i; + //for(i = 0; i < 255; ++i) + // signal(i, sighndlr); + signal(SIGCHLD, sighndlr); + signal(SIGSEGV, sighndlr); + for(i = 0; i < 10; ++i){ + pid_t p = create_child(); + if(p){ + printf("child #%d with PID %d\n", i, p); + while(!child_killed) + usleep(10000); + }else return 0; + } + for(i = 0; i < 10; ++i){ + if(pthread_create(&athread, NULL, thrfnctn, NULL)) + return -1; + printf("thread #%d\n", i); + while(pthread_kill(athread, 0) != ESRCH) + usleep(1000); + pthread_join(athread, NULL); + } + return 0; +} + diff --git a/sigtest.c b/sigtest.c new file mode 100644 index 0000000..b9e6c9e --- /dev/null +++ b/sigtest.c @@ -0,0 +1,45 @@ +#include +#include +#include +#include +#include +#include + +volatile pid_t childpid = 0; + +void signal_handler(int sig){ + printf("PID %zd got signal %d, die\n", getpid(), sig); + if(childpid) + kill(childpid, SIGTERM); + exit(sig); +} + +pid_t create_child(){ + int i; + pid_t p = fork(); + if(p == 0){ + prctl(PR_SET_PDEATHSIG, SIGTERM); // send SIGTERM to child when parent dies + printf("child\n"); + sleep(1); + } + return p; +} + +int main(){ + int i = 0; + signal(SIGTERM, signal_handler); // kill (-15) + signal(SIGINT, signal_handler); // ctrl+C + signal(SIGQUIT, signal_handler); // ctrl+\ . + signal(SIGTSTP, SIG_IGN); // ctrl+Z + signal(SIGSEGV, signal_handler); + printf("my PID: %zd\n", getpid()); + while(1){ + childpid = create_child(); + if(childpid){ + printf("child #%d with PID %d\n", ++i, childpid); + wait(NULL); + printf("died\n"); + }else return 0; + } + return 0; +}