X-Git-Url: http://git.cinelerra-gg.org/git/?a=blobdiff_plain;f=cinelerra-5.1%2Fcinelerra%2Fforkbase.C;h=5886424dd7dd1b1a7977b93530dab89fc9d30151;hb=219e9cae947fc9454f65c210d600800158d798fb;hp=8e87cb3d0678f4bf9319b9f55b7129c968b36454;hpb=efb3600851fd27b13d3053ffbdb6434535580bfd;p=goodguy%2Fhistory.git diff --git a/cinelerra-5.1/cinelerra/forkbase.C b/cinelerra-5.1/cinelerra/forkbase.C index 8e87cb3d..5886424d 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,37 +58,36 @@ ForkBase::~ForkBase() if( parent_fd >= 0 ) close(parent_fd); } -int ForkChild::child_iteration() +// return 1 parent is running +int ForkChild::is_running() { - int ret = read_child(100); - if( ret <= 0 ) return ret; - return handle_child(); + return !ppid || !kill(ppid, 0) ? 1 : 0; } 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 // Return 0 if timeout // Return 1 if success -int ForkBase::read_timeout(int ms, int fd, void *data, int bytes) +int ForkBase::read_timeout(int64_t usec, int fd, void *data, int bytes) { fd_set rfds; struct timeval timeout_struct; @@ -96,18 +95,19 @@ int ForkBase::read_timeout(int ms, int fd, void *data, int bytes) uint8_t *bp = (uint8_t *)data; while( bytes_read < bytes ) { - timeout_struct.tv_sec = ms / 1000; - timeout_struct.tv_usec = (ms % 1000) * 1000; + timeout_struct.tv_sec = usec / 1000000; + timeout_struct.tv_usec = usec % 1000000; 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; } @@ -119,10 +119,10 @@ int ForkBase::is_running() return !pid || !kill(pid, 0) ? 1 : 0; } -int ForkBase::read_parent(int ms) +int ForkBase::read_parent(int64_t usec) { token_bfr_t bfr; - int ret = read_timeout(ms, parent_fd, &bfr, sizeof(bfr)); + int ret = read_timeout(usec, parent_fd, &bfr, sizeof(bfr)); if( ret > 0 ) { parent_token = bfr.token; parent_bytes = bfr.bytes; @@ -130,17 +130,21 @@ int ForkBase::read_parent(int ms) delete [] parent_data; parent_data = new uint8_t[parent_allocated = parent_bytes]; } - if( parent_bytes ) - ret = read_timeout(1000, parent_fd, parent_data, parent_bytes); + if( parent_bytes ) { + ret = read_timeout(1000000, 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; } -int ForkBase::read_child(int ms) +int ForkBase::read_child(int64_t usec) { token_bfr_t bfr; - int ret = read_timeout(ms, child_fd, &bfr, sizeof(bfr)); + int ret = read_timeout(usec, child_fd, &bfr, sizeof(bfr)); if( ret > 0 ) { child_token = bfr.token; child_bytes = bfr.bytes; @@ -148,56 +152,75 @@ int ForkBase::read_child(int ms) delete [] child_data; child_data = new uint8_t[child_allocated = child_bytes]; } - if( child_bytes ) - ret = read_timeout(1000, child_fd, child_data, child_bytes); + if( child_bytes ) { + ret = read_timeout(1000000, 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; } ForkChild::ForkChild() { - done = 0; + parent_done = 0; } ForkChild::~ForkChild() { } -int ForkChild::handle_child() -{ - printf("ForkChild::handle_child %d\n", __LINE__); - return 0; -} - ForkParent::ForkParent() : Thread(1, 0, 0) { - lock = new Mutex("ForkParent::lock"); - done = -1; + parent_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 @@ -217,7 +240,7 @@ int ForkParent::handle_parent() void ForkParent::start() { - done = 0; + parent_done = 0; Thread::start(); } @@ -225,15 +248,16 @@ 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(); } void ForkParent::run() { - while( !done && parent_iteration() >= 0 ); - done = 1; + while( !parent_done && parent_iteration() >= 0 ); + parent_done = 1; }