X-Git-Url: http://git.cinelerra-gg.org/git/?p=goodguy%2Fhistory.git;a=blobdiff_plain;f=cinelerra-5.1%2Fcinelerra%2Fforkbase.C;h=174019ddd6c27f1d07c604b6c08200bfc8103650;hp=8e87cb3d0678f4bf9319b9f55b7129c968b36454;hb=803cf48f8f7ee246eb5473e55fc2125e8b398250;hpb=efb3600851fd27b13d3053ffbdb6434535580bfd diff --git a/cinelerra-5.1/cinelerra/forkbase.C b/cinelerra-5.1/cinelerra/forkbase.C index 8e87cb3d..174019dd 100644 --- a/cinelerra-5.1/cinelerra/forkbase.C +++ b/cinelerra-5.1/cinelerra/forkbase.C @@ -32,8 +32,9 @@ #include ForkBase::ForkBase() + : Mutex("ForkBase::lock") { - pid = 0; + ppid = pid = 0; child = 0; child_fd = -1; @@ -47,7 +48,6 @@ ForkBase::ForkBase() parent_bytes = 0; parent_allocated = 0; parent_data = 0; - } ForkBase::~ForkBase() @@ -58,6 +58,12 @@ ForkBase::~ForkBase() if( parent_fd >= 0 ) close(parent_fd); } +// return 1 parent is running +int ForkChild::is_running() +{ + return !ppid || !kill(ppid, 0) ? 1 : 0; +} + int ForkChild::child_iteration() { int ret = read_child(100); @@ -67,22 +73,22 @@ int ForkChild::child_iteration() void ForkParent::start_child() { - lock->lock("ForkParent::new_child"); + lock("ForkParent::new_child"); int sockets[2]; // Create the process & socket pair. socketpair(AF_UNIX, SOCK_STREAM, 0, sockets); child_fd = sockets[0]; parent_fd = sockets[1]; + ppid = getpid(); pid = fork(); if( !pid ) { // child process - BC_Signals::reset_locks(); - BC_Signals::set_sighup_exit(1); - TheList::reset(); ForkChild *child = new_fork(); child->child_fd = child_fd; child->parent_fd = parent_fd; + child->ppid = ppid; child->run(); + delete child; _exit(0); } - lock->unlock(); + unlock(); } // Return -1 if the parent is dead @@ -101,13 +107,14 @@ int ForkBase::read_timeout(int ms, int fd, void *data, int bytes) FD_ZERO(&rfds); FD_SET(fd, &rfds); int result = select(fd+1, &rfds, 0, 0, &timeout_struct); + if( result < 0 ) perror("read_timeout select"); if( result < 0 || !is_running() ) return -1; if( !result && !bytes_read ) return 0; int fragment = read(fd, bp + bytes_read, bytes - bytes_read); + if( fragment < 0 ) perror("read_timeout read"); if( fragment < 0 || !is_running() ) return -1; if( fragment > 0 ) bytes_read += fragment; } - return 1; } @@ -130,10 +137,14 @@ int ForkBase::read_parent(int ms) delete [] parent_data; parent_data = new uint8_t[parent_allocated = parent_bytes]; } - if( parent_bytes ) + if( parent_bytes ) { ret = read_timeout(1000, parent_fd, parent_data, parent_bytes); + if( !ret ) { + printf("read_parent timeout: %d\n", parent_fd); + ret = -1; + } + } } -//if( ret < 0 ) printf("read_parent timeout\n"); return ret; } @@ -148,28 +159,47 @@ int ForkBase::read_child(int ms) delete [] child_data; child_data = new uint8_t[child_allocated = child_bytes]; } - if( child_bytes ) + if( child_bytes ) { ret = read_timeout(1000, child_fd, child_data, child_bytes); + if( !ret ) { + printf("read_child timeout: %d\n", child_fd); + ret = -1; + } + } } -//if( ret < 0 ) printf("read_child timeout\n"); return ret; } +void ForkBase::send_bfr(int fd, const void *bfr, int len) +{ + int ret = 0; + for( int retries=10; --retries>=0 && (ret=write(fd, bfr, len)) < 0; ) { + printf("send_bfr socket(%d) write error: %d/%d bytes\n%m\n", fd,ret,len); + usleep(100000); + } + if( ret < len ) + printf("send_bfr socket(%d) write short: %d/%d bytes\n%m\n", fd,ret,len); +} + int ForkBase::send_parent(int64_t token, const void *data, int bytes) { + lock("ForkBase::send_parent"); token_bfr_t bfr; memset(&bfr, 0, sizeof(bfr)); bfr.token = token; bfr.bytes = bytes; - write(child_fd, &bfr, sizeof(bfr)); - if( data && bytes ) write(child_fd, data, bytes); + send_bfr(child_fd, &bfr, sizeof(bfr)); + if( data && bytes ) send_bfr(child_fd, data, bytes); + unlock(); return 0; } int ForkBase::send_child(int64_t token, const void *data, int bytes) { + lock("ForkBase::send_child"); token_bfr_t bfr; memset(&bfr, 0, sizeof(bfr)); bfr.token = token; bfr.bytes = bytes; - write(parent_fd, &bfr, sizeof(bfr)); - if( data && bytes ) write(parent_fd, data, bytes); + send_bfr(parent_fd, &bfr, sizeof(bfr)); + if( data && bytes ) send_bfr(parent_fd, data, bytes); + unlock(); return 0; } @@ -191,13 +221,19 @@ int ForkChild::handle_child() ForkParent::ForkParent() : Thread(1, 0, 0) { - lock = new Mutex("ForkParent::lock"); done = -1; } ForkParent::~ForkParent() { - delete lock; +} + +// return 1 child is running +int ForkParent::is_running() +{ + int status = 0; + if( waitpid(pid, &status, WNOHANG) < 0 ) return 0; + return !kill(pid, 0) ? 1 : 0; } // Return -1,0,1 if dead,timeout,success @@ -225,8 +261,9 @@ void ForkParent::stop() { if( is_running() ) { send_child(EXIT_CODE, 0, 0); - int status = 0; - waitpid(pid, &status, 0); + int retry = 10; + while( --retry>=0 && is_running() ) usleep(100000); + if( retry < 0 ) kill(pid, SIGKILL); } join(); }