static void * wd_thread_negotiation(void * arg) { WdPacketThreadArg * thread_arg; int sock; uintptr_t rtn; WdPacket recv_packet; WdInfo * p; char pack_str[WD_MAX_PACKET_STRING]; int pack_str_len; thread_arg = (WdPacketThreadArg *)arg; sock = thread_arg->sock; gettimeofday(&(thread_arg->packet->send_time), NULL); if (strlen(pool_config->wd_authkey)) { /* calculate hash from packet */ pack_str_len = wd_packet_to_string(thread_arg->packet, pack_str, sizeof(pack_str)); wd_calc_hash(pack_str, pack_str_len, thread_arg->packet->hash); } /* packet send to target watchdog */ rtn = (uintptr_t)wd_send_packet(sock, thread_arg->packet); if (rtn != WD_OK) { close(sock); pthread_exit((void *)rtn); } /* receive response packet */ memset(&recv_packet,0,sizeof(WdPacket)); rtn = (uintptr_t)wd_recv_packet(sock, &recv_packet); if (rtn != WD_OK) { close(sock); pthread_exit((void *)rtn); } rtn = WD_OK; switch (thread_arg->packet->packet_no) { case WD_ADD_REQ: if (recv_packet.packet_no == WD_ADD_ACCEPT) { memcpy(thread_arg->target, &(recv_packet.wd_body.wd_info),sizeof(WdInfo)); } else { rtn = WD_NG; } break; case WD_STAND_FOR_MASTER: if (recv_packet.packet_no == WD_MASTER_EXIST) { p = &(recv_packet.wd_body.wd_info); wd_set_wd_info(p); rtn = WD_NG; } break; case WD_STAND_FOR_LOCK_HOLDER: case WD_DECLARE_LOCK_HOLDER: if (recv_packet.packet_no == WD_LOCK_HOLDER_EXIST) { rtn = WD_NG; } break; case WD_DECLARE_NEW_MASTER: case WD_RESIGN_LOCK_HOLDER: if (recv_packet.packet_no != WD_READY) { rtn = WD_NG; } break; case WD_START_RECOVERY: case WD_FAILBACK_REQUEST: case WD_DEGENERATE_BACKEND: case WD_PROMOTE_BACKEND: rtn = (recv_packet.packet_no == WD_NODE_FAILED) ? WD_NG : WD_OK; break; case WD_UNLOCK_REQUEST: rtn = (recv_packet.packet_no == WD_LOCK_FAILED) ? WD_NG : WD_OK; break; case WD_AUTH_FAILED: pool_log("wd_thread_negotiation: watchdog authentication failed"); rtn = WD_NG; break; default: break; } close(sock); pthread_exit((void *)rtn); }
pid_t wd_child(int fork_wait_time) { int sock; int fd; int rtn; pid_t pid = 0; pid = fork(); if (pid != 0) { if (pid == -1) pool_error("wd_child: fork() failed."); return pid; } if (fork_wait_time > 0) { sleep(fork_wait_time); } myargv = save_ps_display_args(myargc, myargv); POOL_SETMASK(&UnBlockSig); signal(SIGTERM, wd_child_exit); signal(SIGINT, wd_child_exit); signal(SIGQUIT, wd_child_exit); signal(SIGCHLD, SIG_IGN); signal(SIGHUP, SIG_IGN); signal(SIGUSR1, SIG_IGN); signal(SIGUSR2, SIG_IGN); signal(SIGPIPE, SIG_IGN); signal(SIGALRM, SIG_IGN); init_ps_display("", "", "", ""); if (WD_List == NULL) { /* memory allocate is not ready */ wd_child_exit(15); } sock = wd_create_recv_socket(WD_MYSELF->wd_port); if (sock < 0) { /* socket create failed */ wd_child_exit(15); } set_ps_display("watchdog", false); /* child loop */ for(;;) { WdPacket buf; fd = wd_accept(sock); if (fd < 0) { continue; } rtn = wd_recv_packet(fd, &buf); if (rtn == WD_OK) { wd_send_response(fd, &buf); } close(fd); } return pid; }
pid_t wd_child(int fork_wait_time) { int sock; volatile int fd; int rtn; pid_t pid = 0; sigjmp_buf local_sigjmp_buf; pid = fork(); if (pid != 0) { if (pid == -1) ereport(PANIC, (errmsg("failed to fork a watchdog process"))); return pid; } on_exit_reset(); processType = PT_WATCHDOG; if (fork_wait_time > 0) { sleep(fork_wait_time); } POOL_SETMASK(&UnBlockSig); signal(SIGTERM, wd_child_exit); signal(SIGINT, wd_child_exit); signal(SIGQUIT, wd_child_exit); signal(SIGCHLD, SIG_IGN); signal(SIGHUP, SIG_IGN); signal(SIGUSR1, SIG_IGN); signal(SIGUSR2, SIG_IGN); signal(SIGPIPE, SIG_IGN); signal(SIGALRM, SIG_IGN); init_ps_display("", "", "", ""); if (WD_List == NULL) { /* memory allocate is not ready */ wd_child_exit(15); } /* Create per loop iteration memory context */ ProcessLoopContext = AllocSetContextCreate(TopMemoryContext, "wd_child_main_loop", ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); MemoryContextSwitchTo(TopMemoryContext); sock = wd_create_recv_socket(WD_MYSELF->wd_port); if (sock < 0) { /* socket create failed */ wd_child_exit(15); } set_ps_display("watchdog", false); if (sigsetjmp(local_sigjmp_buf, 1) != 0) { /* Since not using PG_TRY, must reset error stack by hand */ if(fd > 0) close(fd); error_context_stack = NULL; EmitErrorReport(); MemoryContextSwitchTo(TopMemoryContext); FlushErrorState(); } /* We can now handle ereport(ERROR) */ PG_exception_stack = &local_sigjmp_buf; /* child loop */ for(;;) { MemoryContextSwitchTo(ProcessLoopContext); MemoryContextResetAndDeleteChildren(ProcessLoopContext); fd = -1; WdPacket buf; fd = wd_accept(sock); if (fd < 0) { continue; } rtn = wd_recv_packet(fd, &buf); if (rtn == WD_OK) { wd_send_response(fd, &buf); } close(fd); } return pid; }