add child process guard; fix error with steppers server disconnection

This commit is contained in:
Edward Emelianov 2021-10-28 16:00:14 +03:00
parent 237b11d640
commit 39b9cee77c
5 changed files with 69 additions and 23 deletions

View File

@ -46,7 +46,6 @@ static void changeformat(){
if(!theCam) return; if(!theCam) return;
if(maxformat.h < 1 || maxformat.w < 1){ if(maxformat.h < 1 || maxformat.w < 1){
WARNX("Bad max format data"); WARNX("Bad max format data");
LOGWARN("Bad max format data");
return; return;
} }
if(stepformat.h < 1 || stepformat.w < 1){ if(stepformat.h < 1 || stepformat.w < 1){

View File

@ -28,14 +28,14 @@ void makedebuglog();
void *my_malloc(size_t N, size_t S); void *my_malloc(size_t N, size_t S);
void my_free(void *ptr); void my_free(void *ptr);
#undef FNAME //#undef FNAME
#undef ALLOC #undef ALLOC
#undef MALLOC #undef MALLOC
#undef FREE #undef FREE
#define _LOG(...) do{if(!debuglog) makedebuglog(); sl_putlogt(1, debuglog, LOGLEVEL_ERR, __VA_ARGS__);}while(0) #define _LOG(...) do{if(!debuglog) makedebuglog(); sl_putlogt(1, debuglog, LOGLEVEL_ERR, __VA_ARGS__);}while(0)
#define DBGLOG(...) do{_LOG("%s (%s, line %d)", __func__, __FILE__, __LINE__); \ #define DBGLOG(...) do{_LOG("%s (%s, line %d)", __func__, __FILE__, __LINE__); \
sl_putlogt(0, debuglog, LOGLEVEL_ERR, __VA_ARGS__);}while(0) sl_putlogt(0, debuglog, LOGLEVEL_ERR, __VA_ARGS__);}while(0)
#define FNAME() _LOG("%s (%s, line %d)", __func__, __FILE__, __LINE__) //#define FNAME() _LOG("%s (%s, line %d)", __func__, __FILE__, __LINE__)
#define _str(x) #x #define _str(x) #x
#define ALLOC(type, var, size) DBGLOG("%s *%s = ALLOC(%d)", _str(type), _str(var), size*sizeof(type)); \ #define ALLOC(type, var, size) DBGLOG("%s *%s = ALLOC(%d)", _str(type), _str(var), size*sizeof(type)); \

View File

@ -266,11 +266,12 @@ void process_file(Image *I){
outp = equalize(I, 3, theconf.throwpart); outp = equalize(I, 3, theconf.throwpart);
else else
outp = linear(I, 3); outp = linear(I, 3);
static Pattern *cross = NULL; static Pattern *cross = NULL, *crossL = NULL;
if(!cross) cross = Pattern_xcross(33, 33); if(!cross) cross = Pattern_xcross(33, 33);
if(!crossL) crossL = Pattern_xcross(51, 51);
Img3 i3 = {.data = outp, .w = I->width, .h = H}; Img3 i3 = {.data = outp, .w = I->width, .h = H};
// draw fiber center position // draw fiber center position
Pattern_draw3(&i3, cross, theconf.xtarget-theconf.xoff, H-(theconf.ytarget-theconf.yoff), C_B); Pattern_draw3(&i3, crossL, theconf.xtarget-theconf.xoff, H-(theconf.ytarget-theconf.yoff), C_R);
if(objctr){ // draw crosses @ objects' centers if(objctr){ // draw crosses @ objects' centers
int H = I->height; int H = I->height;
// draw current star centroid // draw current star centroid
@ -280,7 +281,7 @@ void process_file(Image *I){
yc = Objects[0].yc + theconf.yoff; yc = Objects[0].yc + theconf.yoff;
// draw other centroids // draw other centroids
for(int i = 1; i < objctr; ++i) for(int i = 1; i < objctr; ++i)
Pattern_draw3(&i3, cross, Objects[i].xc, H-Objects[i].yc, C_R); Pattern_draw3(&i3, cross, Objects[i].xc, H-Objects[i].yc, C_B);
}else{xc = -1.; yc = -1.;} }else{xc = -1.; yc = -1.;}
char *tmpnm = MALLOC(char, strlen(GP->outputjpg) + 5); char *tmpnm = MALLOC(char, strlen(GP->outputjpg) + 5);
sprintf(tmpnm, "%s-tmp", GP->outputjpg); sprintf(tmpnm, "%s-tmp", GP->outputjpg);

View File

@ -21,6 +21,8 @@
#include <signal.h> // signal #include <signal.h> // signal
#include <stdio.h> #include <stdio.h>
#include <string.h> // strdup #include <string.h> // strdup
#include <sys/prctl.h> //prctl
#include <sys/wait.h> // wait
#include "cmdlnopts.h" #include "cmdlnopts.h"
#include "config.h" #include "config.h"
@ -38,7 +40,7 @@ static InputType tp;
void signals(int sig){ void signals(int sig){
if(sig){ if(sig){
signal(sig, SIG_IGN); signal(sig, SIG_IGN);
DBG("Get signal %d, quit.\n", sig); DBG("Get signal %d.", sig);
} }
stopwork = TRUE; stopwork = TRUE;
DBG("exit %d", sig); DBG("exit %d", sig);
@ -181,7 +183,6 @@ int main(int argc, char *argv[]){
theconf.stpserverport = GP->pusiservport; theconf.stpserverport = GP->pusiservport;
} }
} }
setpostprocess(GP->processing);
check4running(self, GP->pidfile); check4running(self, GP->pidfile);
DBG("%s started, snippets library version is %s\n", self, sl_libversion()); DBG("%s started, snippets library version is %s\n", self, sl_libversion());
free(self); self = NULL; free(self); self = NULL;
@ -190,6 +191,21 @@ int main(int argc, char *argv[]){
signal(SIGINT, signals); // ctrl+C - quit signal(SIGINT, signals); // ctrl+C - quit
signal(SIGQUIT, signals); // ctrl+\ - quit signal(SIGQUIT, signals); // ctrl+\ - quit
signal(SIGTSTP, SIG_IGN); // ignore ctrl+Z signal(SIGTSTP, SIG_IGN); // ignore ctrl+Z
while(1){ // guard for dead processes
pid_t childpid = fork();
if(childpid){ // father
LOGMSG("create child with PID %d\n", childpid);
DBG("Created child with PID %d\n", childpid);
wait(NULL);
LOGMSG("child %d died\n", childpid);
WARNX("Child %d died\n", childpid);
sleep(5);
}else{ // son
prctl(PR_SET_PDEATHSIG, SIGTERM); // send SIGTERM to child when parent dies
break; // go out to normal functional
}
}
setpostprocess(GP->processing);
if(GP->logXYname) openXYlog(GP->logXYname); if(GP->logXYname) openXYlog(GP->logXYname);
LOGMSG("Start application..."); LOGMSG("Start application...");
LOGDBG("xtag=%g, ytag=%g", theconf.xtarget, theconf.ytarget); LOGDBG("xtag=%g, ytag=%g", theconf.xtarget, theconf.ytarget);

View File

@ -133,7 +133,8 @@ static double Xtarget = 0., Ytarget = 0.;
static volatile atomic_bool chfocus = FALSE; static volatile atomic_bool chfocus = FALSE;
static volatile atomic_int newfocpos = 0; static volatile atomic_int newfocpos = 0;
static int sockfd = -1; // server file descriptor static volatile atomic_int sockfd = -1; // server file descriptor
static volatile atomic_bool motorsoff = FALSE; // flag to disconnect
// mutex for message sending // mutex for message sending
static pthread_mutex_t sendmesg_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t sendmesg_mutex = PTHREAD_MUTEX_INITIALIZER;
@ -144,15 +145,24 @@ static volatile atomic_int dUmove = 0, dVmove = 0;
static volatile atomic_bool Umoving = FALSE, Vmoving = FALSE, Fmoving = FALSE; static volatile atomic_bool Umoving = FALSE, Vmoving = FALSE, Fmoving = FALSE;
static uint8_t fixerr = 0; // ==1 if can't fixed static uint8_t fixerr = 0; // ==1 if can't fixed
static void pusi_disc(){
motorsoff = TRUE;
}
static void pusi_disconnect(){ static void pusi_disconnect(){
if(sockfd > -1) close(sockfd); DBG("Try to disconnect");
sockfd = -1; if(sockfd > -1){
DBG("sockfd closed");
close(sockfd);
}
Umoving = Vmoving = Fmoving = ismoving = FALSE; Umoving = Vmoving = Fmoving = ismoving = FALSE;
state = PUSI_DISCONN; state = PUSI_DISCONN;
sockfd = -1;
LOGWARN("Canserver disconnected"); LOGWARN("Canserver disconnected");
} }
static int too_much_errors(){ static int too_much_errors(){
// FNAME();
if(++errctr >= MAX_ERR_CTR){ if(++errctr >= MAX_ERR_CTR){
LOGERR("Canserver: too much errors -> DISCONNECT"); LOGERR("Canserver: too much errors -> DISCONNECT");
errctr = 0; errctr = 0;
@ -165,6 +175,7 @@ static int too_much_errors(){
#define clr_errors() do{errctr = 0;}while(0) #define clr_errors() do{errctr = 0;}while(0)
static char *findval(const char *par, const char *statusmesg){ static char *findval(const char *par, const char *statusmesg){
// FNAME();
if(!statusmesg || !par) return NULL; if(!statusmesg || !par) return NULL;
char *pair = strcasestr(statusmesg, par); char *pair = strcasestr(statusmesg, par);
if(!pair) return NULL; if(!pair) return NULL;
@ -184,6 +195,7 @@ static char *findval(const char *par, const char *statusmesg){
* @return TRUE if parameter found and set `val` to its value * @return TRUE if parameter found and set `val` to its value
*/ */
static int getparval(const char *par, const char *statusmesg, double *val){ static int getparval(const char *par, const char *statusmesg, double *val){
// FNAME();
char *parval = findval(par, statusmesg); char *parval = findval(par, statusmesg);
if(!parval) return FALSE; if(!parval) return FALSE;
if(!val) return TRUE; if(!val) return TRUE;
@ -192,6 +204,7 @@ static int getparval(const char *par, const char *statusmesg, double *val){
} }
// the same as getparval, but check for "=OK" // the same as getparval, but check for "=OK"
static int getOKval(const char *par, const char *statusmesg){ static int getOKval(const char *par, const char *statusmesg){
// FNAME();
//DBG("getOKval('%s', '%s')", par, statusmesg); //DBG("getOKval('%s', '%s')", par, statusmesg);
char *parval = findval(par, statusmesg); char *parval = findval(par, statusmesg);
if(!parval) return FALSE; if(!parval) return FALSE;
@ -230,6 +243,7 @@ static int canread(){
// clear incoming buffer // clear incoming buffer
static void clearbuf(){ static void clearbuf(){
// FNAME();
if(sockfd < 0) return; if(sockfd < 0) return;
char buf[256] = {0}; char buf[256] = {0};
while(canread() && 0 < read(sockfd, buf, 256)) DBG("clearbuf: %s", buf); while(canread() && 0 < read(sockfd, buf, 256)) DBG("clearbuf: %s", buf);
@ -241,12 +255,14 @@ static void clearbuf(){
* @return FALSE if timeout or no "OK" * @return FALSE if timeout or no "OK"
*/ */
static int waitOK(char **retval){ static int waitOK(char **retval){
// FNAME();
if(sockfd < 0) return FALSE; if(sockfd < 0) return FALSE;
#define BUFFERSZ (2047) #define BUFFERSZ (2047)
char buf[BUFFERSZ+1]; char buf[BUFFERSZ+1];
int Nread = 0, ctr = 0; int Nread = 0, ctr = 0;
double t0 = dtime(); double t0 = dtime();
while(dtime() - t0 < WAITANSTIME && Nread < BUFFERSZ){ //DBG("read ans");
while(dtime() - t0 < WAITANSTIME && Nread < BUFFERSZ && sockfd > 0){
if(!canread()){ if(!canread()){
//DBG("No answer @ %d try", ctr); //DBG("No answer @ %d try", ctr);
if(++ctr > 3) break; if(++ctr > 3) break;
@ -258,8 +274,8 @@ static int waitOK(char **retval){
if(n == 0) break; if(n == 0) break;
if(n < 0) return FALSE; // disconnect or error if(n < 0) return FALSE; // disconnect or error
Nread += n; Nread += n;
buf[Nread] = 0;
} }
buf[Nread] = 0;
//DBG("All buffer: '%s'", buf); //DBG("All buffer: '%s'", buf);
int ret = FALSE; int ret = FALSE;
char *ok = strstr(buf, ANSOK); char *ok = strstr(buf, ANSOK);
@ -286,6 +302,7 @@ static int waitOK(char **retval){
* @return FALSE if failed (should reconnect) * @return FALSE if failed (should reconnect)
*/ */
static int send_message(const char *msg, char **ans){ static int send_message(const char *msg, char **ans){
// FNAME();
if(!msg || sockfd < 0) return FALSE; if(!msg || sockfd < 0) return FALSE;
size_t L = strlen(msg); size_t L = strlen(msg);
if(pthread_mutex_lock(&sendmesg_mutex)) return FALSE; if(pthread_mutex_lock(&sendmesg_mutex)) return FALSE;
@ -307,6 +324,7 @@ static int send_message(const char *msg, char **ans){
* @return amount of args found (0 - if answer is wrong or no n'th arg found) * @return amount of args found (0 - if answer is wrong or no n'th arg found)
*/ */
static int getRansArg(char *ans, uint8_t buf[8]){ static int getRansArg(char *ans, uint8_t buf[8]){
// FNAME();
//DBG("check relay answer, ans: %s", ans); //DBG("check relay answer, ans: %s", ans);
if(!ans) return 0; if(!ans) return 0;
if(strncmp(ans, RelayAns, sizeof(RelayAns)-1)) return 0; // bad answer if(strncmp(ans, RelayAns, sizeof(RelayAns)-1)) return 0; // bad answer
@ -321,6 +339,7 @@ static int getRansArg(char *ans, uint8_t buf[8]){
* @return FALSE if failed * @return FALSE if failed
*/ */
static int chkRelay(){ static int chkRelay(){
// FNAME();
char *ans = NULL; char *ans = NULL;
char buf[512]; char buf[512];
uint8_t canbuf[8]; uint8_t canbuf[8];
@ -348,6 +367,7 @@ rtn:
} }
static void send_message_nocheck(const char *msg){ static void send_message_nocheck(const char *msg){
// FNAME();
if(!msg || sockfd < 0) return; if(!msg || sockfd < 0) return;
size_t L = strlen(msg); size_t L = strlen(msg);
if(pthread_mutex_lock(&sendmesg_mutex)) return; if(pthread_mutex_lock(&sendmesg_mutex)) return;
@ -382,7 +402,6 @@ static int setSpeed(const char *mesg, const char *name){
* @return FALSE if failed * @return FALSE if failed
*/ */
static int pusi_connect_server(){ static int pusi_connect_server(){
Umoving = Fmoving = Vmoving = ismoving = FALSE;
DBG("pusi_connect(%d)", theconf.stpserverport); DBG("pusi_connect(%d)", theconf.stpserverport);
char port[10]; char port[10];
snprintf(port, 10, "%d", theconf.stpserverport); snprintf(port, 10, "%d", theconf.stpserverport);
@ -439,6 +458,7 @@ static pthread_t processingthread;
* @return FALSE if failed to connect immediately * @return FALSE if failed to connect immediately
*/ */
int pusi_connect(){ int pusi_connect(){
DBG("Try to connect");
int c = pusi_connect_server(); int c = pusi_connect_server();
if(pthread_create(&processingthread, NULL, pusi_process_states, NULL)){ if(pthread_create(&processingthread, NULL, pusi_process_states, NULL)){
LOGERR("pthread_create() for pusirobo server failed"); LOGERR("pthread_create() for pusirobo server failed");
@ -447,14 +467,9 @@ int pusi_connect(){
return c; return c;
} }
// stop processing & disconnect
static void pusi_stop(){
pthread_join(processingthread, NULL);
pusi_disconnect();
}
// return TRUE if motor is stopped // return TRUE if motor is stopped
static int moving_finished(const char *mesgstatus, volatile atomic_int *position){ static int moving_finished(const char *mesgstatus, volatile atomic_int *position){
// FNAME();
double val = 0.; double val = 0.;
char *ans = NULL; char *ans = NULL;
int ret = TRUE; int ret = TRUE;
@ -732,7 +747,7 @@ static void pusi_process_corrections(double X, double Y){
static int pusi_setstate(pusistate newstate){ static int pusi_setstate(pusistate newstate){
if(newstate == state) return TRUE; if(newstate == state) return TRUE;
if(newstate == PUSI_DISCONN){ if(newstate == PUSI_DISCONN){
pusi_disconnect(); pusi_disc();
return TRUE; return TRUE;
} }
if(state == PUSI_DISCONN){ if(state == PUSI_DISCONN){
@ -748,6 +763,7 @@ static int pusi_setstate(pusistate newstate){
// get current status (global variable stepstatus) // get current status (global variable stepstatus)
// return JSON string with different parameters // return JSON string with different parameters
static char *pusi_status(const char *messageid, char *buf, int buflen){ static char *pusi_status(const char *messageid, char *buf, int buflen){
// FNAME();
int l; int l;
char *bptr = buf; char *bptr = buf;
const char *s = NULL, *stage = NULL; const char *s = NULL, *stage = NULL;
@ -849,6 +865,7 @@ static strstate stringstatuses[] = {
// try to set new status (global variable stepstatus) // try to set new status (global variable stepstatus)
static char *set_pusistatus(const char *newstatus, char *buf, int buflen){ static char *set_pusistatus(const char *newstatus, char *buf, int buflen){
// FNAME();
strstate *s = stringstatuses; strstate *s = stringstatuses;
pusistate newstate = PUSI_UNDEFINED; pusistate newstate = PUSI_UNDEFINED;
while(s->str){ while(s->str){
@ -882,22 +899,34 @@ static char *set_pusistatus(const char *newstatus, char *buf, int buflen){
// MAIN THREAD // MAIN THREAD
static void *pusi_process_states(_U_ void *arg){ static void *pusi_process_states(_U_ void *arg){
FNAME(); // FNAME();
static bool first = TRUE; // flag for logging when can't reconnect static bool first = TRUE; // flag for logging when can't reconnect
while(!stopwork){ while(!stopwork){
usleep(10000); usleep(10000);
// check for disconnection flag
if(motorsoff){
motorsoff = FALSE;
pusi_disconnect();
sleep(1);
continue;
}
// check for moving // check for moving
if(state == PUSI_DISCONN){ if(state == PUSI_DISCONN){
DBG("DISCONNECTED - try to connect");
sleep(1); sleep(1);
pusi_connect_server(); pusi_connect_server();
continue; continue;
} }
// check relay // check relay
//DBG("relay");
chkRelay(); chkRelay();
//DBG("U");
if(moving_finished(Ustatus, &Uposition)) Umoving = FALSE; if(moving_finished(Ustatus, &Uposition)) Umoving = FALSE;
else Umoving = TRUE; else Umoving = TRUE;
//DBG("V");
if(moving_finished(Vstatus, &Vposition)) Vmoving = FALSE; if(moving_finished(Vstatus, &Vposition)) Vmoving = FALSE;
else Vmoving = TRUE; else Vmoving = TRUE;
//DBG("F");
if(moving_finished(Fstatus, &Fposition)) Fmoving = FALSE; if(moving_finished(Fstatus, &Fposition)) Fmoving = FALSE;
else Fmoving = TRUE; else Fmoving = TRUE;
if(Umoving || Vmoving || Fmoving) ismoving = TRUE; if(Umoving || Vmoving || Fmoving) ismoving = TRUE;
@ -975,6 +1004,7 @@ static void *pusi_process_states(_U_ void *arg){
break; break;
} }
} }
DBG("thread stopped");
return NULL; return NULL;
} }
@ -1045,7 +1075,7 @@ static char *relaycmd(const char *val, char *buf, int buflen){
} }
steppersproc pusyCANbus = { steppersproc pusyCANbus = {
.stepdisconnect = pusi_stop, .stepdisconnect = pusi_disc,
.proc_corr = pusi_process_corrections, .proc_corr = pusi_process_corrections,
.stepstatus = pusi_status, .stepstatus = pusi_status,
.setstepstatus = set_pusistatus, .setstepstatus = set_pusistatus,