diff --git a/sr_port/jnl_write.c b/sr_port/jnl_write.c index 948e8d511..6f2e5610b 100644 --- a/sr_port/jnl_write.c +++ b/sr_port/jnl_write.c @@ -50,6 +50,7 @@ #include "buddy_list.h" /* needed for tp.h */ #include "hashtab_int4.h" /* needed for tp.h */ #include "tp.h" +#include "is_defunct_pid.h" #endif GBLREF uint4 process_id; @@ -122,6 +123,7 @@ void jnl_write(jnl_private_control *jpc, enum jnl_record_type rectype, jnl_recor char *mumps_node_ptr; struct_jrec_align *align_rec; uint4 end_freeaddr; + int4 blocking_pid; # endif assert(MAX_JNL_WRITE_RECURSION_DEPTH > jnl_write_recursion_depth++); @@ -262,8 +264,11 @@ void jnl_write(jnl_private_control *jpc, enum jnl_record_type rectype, jnl_recor ADJUST_CHECKSUM(checksum, csd->jnl_checksum, checksum); SET_JREC_CHECKSUM(jnl_rec, rectype, checksum); if (!in_phase2) - { - assert((!jb->blocked) || (FALSE == is_proc_alive(jb->blocked, 0))); + { /* Check that the pid in jb->blocked is dead if it is not 0. The check handles the case that a pid could be dead + * but its parent could still have not gotten its exit status in which case it could be a defunct. + */ + DEBUG_ONLY(blocking_pid = jb->blocked); + assert(!blocking_pid || is_defunct_pid((uint4)blocking_pid) || (FALSE == is_proc_alive(blocking_pid, 0))); jb->blocked = process_id; } jnl_fs_block_size = jb->fs_block_size; diff --git a/sr_unix/is_defunct_pid.c b/sr_unix/is_defunct_pid.c new file mode 100755 index 000000000..60bef1b3c --- /dev/null +++ b/sr_unix/is_defunct_pid.c @@ -0,0 +1,63 @@ +/**************************************************************** + * * + * Copyright (c) 2019 YottaDB LLC and/or its subsidiaries. * + * All rights reserved. * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +#include "mdef.h" + +#include "gtm_stdio.h" + +#include "is_defunct_pid.h" + +#ifdef DEBUG +GBLREF uint4 process_id; +#endif + +/* ---------------------------------------------- + * Check if input pid is a defunct process (zombie) + * + * Arguments: + * pid - process ID + * + * Return: + * TRUE - If process is a defunct process (i.e. shows up as in ps -ef listing) + * FALSE - Otherwise + * ---------------------------------------------- + */ + +boolean_t is_defunct_pid(int4 pid) +{ + int status; + char procfilename[64]; + boolean_t is_defunct; + FILE *fp; + char pidstate; + + assert(0 != pid); + assert(process_id != pid); + is_defunct = FALSE; /* by default it is not a defunct process */ +# ifdef __linux__ + /* open the /proc//stat file */ + SNPRINTF(procfilename, sizeof(procfilename), "/proc/%d/stat", (int)pid); + fp = fopen(procfilename, "r"); + if (NULL != fp) + { + fscanf(fp, "%*d %*s %c", &pidstate); + is_defunct = ('Z' == pidstate); + fclose(fp); + } +# else + /* This is likely MacOS or Cygwin. Those ports need to implement this functionality using other methods + * (maybe do a "system" call with a "ps -ef | grep defunct" if nothing else is possible). + */ +# error unsupported platform +# endif + return is_defunct; +} diff --git a/sr_unix/is_defunct_pid.h b/sr_unix/is_defunct_pid.h new file mode 100755 index 000000000..a34b5e99c --- /dev/null +++ b/sr_unix/is_defunct_pid.h @@ -0,0 +1,18 @@ +/**************************************************************** + * * + * Copyright (c) 2019 YottaDB LLC and/or its subsidiaries. * + * All rights reserved. * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +#ifndef IS_DEFUNCT_PID_INCLUDED +#define IS_DEFUNCT_PID_INCLUDED + +boolean_t is_defunct_pid(int4 pid); + +#endif /* IS_DEFUNCT_PID_INCLUDED */