int erts_run_erl_log_activity(int timeout,time_t now,time_t last_activity) { char log_alive_buffer[ALIVE_BUFFSIZ+1]; char buf[BUFSIZ]; if (timeout || now - last_activity > LOG_ACTIVITY_MINUTES*60) { /* Either a time out: 15 minutes without action, */ /* or something is coming in right now, but it's a long time */ /* since last time, so let's write a time stamp this message */ struct tm *tmptr; if (LOG_ALIVE_IN_GMT) { tmptr = gmtime(&now); } else { tmptr = localtime(&now); } if (!strftime(log_alive_buffer, ALIVE_BUFFSIZ, LOG_ALIVE_FORMAT, tmptr)) { strn_cpy(log_alive_buffer, sizeof(log_alive_buffer), "(could not format time in 256 positions " "with current format string.)"); } log_alive_buffer[ALIVE_BUFFSIZ] = '\0'; sn_printf(buf, sizeof(buf), "\n===== %s%s\n", timeout?"ALIVE ":"", log_alive_buffer); return erts_run_erl_log_write(buf, strlen(buf)); } return 0; }
int pass_on(ProgramState *s) { SIGSELECT sigsel[] = {0,FM_READ_PTR_REPLY}; union SIGNAL *sig; char child_read_buff[BUFSIZ], pipe_read_buff[BUFSIZ]; struct aiocb child_read_req, pipe_read_req; int rfd, wfd = 0; FmHandle rfh, child_rfh; int outstanding_writes = 0, got_some = 0, child_done = 0; if ((rfd = sf_open(s->r_pipe, O_RDONLY, 0)) < 0) { ERRNO_ERR1(LOG_ERR,"Could not open FIFO '%s' for reading.\n", s->r_pipe); rfd = 0; return 1; } attach(NULL,s->progpid); /* Open the log file */ erts_run_erl_log_open(); efs_examine_fd(rfd,FLIB_FD_HANDLE,&rfh); efs_examine_fd(s->ifd,FLIB_FD_HANDLE,&child_rfh); READ_AIO(child_read_req,s->ifd,BUFSIZ,child_read_buff); READ_AIO(pipe_read_req,rfd,BUFSIZ,pipe_read_buff); while (1) { time_t now,last_activity; time(&last_activity); sig = receive_w_tmo(erts_run_erl_log_alive_minutes()*60000,sigsel); time(&now); if (sig) { erts_run_erl_log_activity(0,now,last_activity); } else { /* timeout */ erts_run_erl_log_activity(1,now,last_activity); continue; } switch (sig->signo) { case OS_ATTACH_SIG: { if (rfd) { sf_close(rfd); rfd = 0; } free_buf(&sig); child_done = 1; /* Make sure to to let all outstanding write request finish */ if (outstanding_writes) break; if (wfd) sf_close(wfd); return 0; } case FM_WRITE_PTR_REPLY: { if (sig->fm_write_ptr.status == EFS_SUCCESS) { if (sig->fm_write_ptr.actual < sig->fm_write_ptr.requested) { WRITE_AIO(wfd, sig->fm_write_ptr.requested-sig->fm_write_ptr.actual, sig->fm_write_ptr.buffer+sig->fm_write_ptr.actual); } } else { /* Assume to_erl has terminated. */ sf_close(wfd); wfd = 0; } free((char*)sig->fm_write_ptr.buffer); aio_dispatch(sig); if ((--outstanding_writes == 0) && child_done) { if (wfd) sf_close(wfd); return 0; } break; } case FM_READ_PTR_REPLY: { /* Child fd */ if (sig->fm_read_ptr.handle == child_rfh) { /* Child terminated */ if (sig->fm_read_ptr.status != EFS_SUCCESS || sig->fm_read_ptr.actual == 0) { if (rfd) { sf_close(rfd); rfd = 0; } if (sig->fm_read_ptr.status != EFS_SUCCESS) { ERROR0(LOG_ERR,"Erlang closed the connection."); aio_dispatch(sig); return 1; } /* child closed connection gracefully */ aio_dispatch(sig); if (outstanding_writes) { child_done = 1; break; } if (wfd) sf_close(wfd); return 0; } else { erts_run_erl_log_write(sig->fm_read_ptr.buffer, sig->fm_read_ptr.actual); if (wfd) { WRITE_AIO(wfd, sig->fm_read_ptr.actual, sig->fm_read_ptr.buffer); outstanding_writes++; } aio_dispatch(sig); READ_AIO(child_read_req, s->ifd,BUFSIZ, child_read_buff); } /* pipe fd */ } else if (sig->fm_read_ptr.handle == rfh) { if (sig->fm_read_ptr.status != EFS_SUCCESS) { if(rfd) sf_close(rfd); if(wfd) sf_close(wfd); aio_dispatch(sig); ERRNO_ERR0(LOG_ERR,"Error in reading from FIFO."); return 1; } if (sig->fm_read_ptr.actual == 0) { /* to_erl closed its end of the pipe */ aio_dispatch(sig); sf_close(rfd); rfd = sf_open(s->r_pipe,O_RDONLY|DONT_BLOCK_PLEASE, 0); if (rfd < 0) { ERRNO_ERR1(LOG_ERR,"Could not open FIFO '%s' for reading.", s->r_pipe); rfd = 0; } else { READ_AIO(pipe_read_req,rfd,BUFSIZ,pipe_read_buff); } got_some = 0; /* reset for next session */ } else { int len = sig->fm_read_ptr.actual; char *buffer = sig->fm_read_ptr.buffer; if (!wfd) { /* Try to open the write pipe to to_erl. Now that we got some data * from to_erl, to_erl should already be reading this pipe - open * should succeed. But in case of error, we just ignore it. */ if ((wfd = sf_open(s->w_pipe, O_WRONLY|DONT_BLOCK_PLEASE, 0)) < 0) { erts_run_erl_log_status("Client expected on FIFO %s, " "but can't open (len=%d)\n", s->w_pipe, sig->fm_read_ptr.actual); sf_close(rfd); rfd = sf_open(s->r_pipe, O_RDONLY|DONT_BLOCK_PLEASE, 0); if (rfd < 0) { ERRNO_ERR1(LOG_ERR,"Could not open FIFO '%s' for reading.", s->r_pipe); return 1; } wfd = 0; } else { #ifdef DEBUG erts_run_erl_log_status("run_erl: %s opened for writing\n", s->w_pipe); #endif } } if (!got_some && wfd && buffer[0] == '\014') { char wbuf[30]; int wlen = sn_printf(wbuf,sizeof(wbuf),"[run_erl v%u-%u]\n", RUN_ERL_HI_VER, RUN_ERL_LO_VER); /* For some reason this, the first write aio seems to not get an FM_WRITE_PTR_REPLY, so we do not do: outstanding_writes++; */ WRITE_AIO(wfd, wlen, wbuf); } got_some = 1; /* Write the message */ #ifdef DEBUG erts_run_erl_log_status("Pty master write; "); #endif len = erts_run_erl_extract_ctrl_seq(buffer,len, s->ofd); if (len > 0) { int wlen = erts_run_erl_write_all(s->ofd, buffer, len); if (wlen != len) { aio_dispatch(sig); ERRNO_ERR0(LOG_ERR,"Error in writing to terminal."); if(rfd) sf_close(rfd); if(wfd) sf_close(wfd); return 1; } } #ifdef DEBUG erts_run_erl_log_status("OK\n"); #endif aio_dispatch(sig); READ_AIO(pipe_read_req,rfd,BUFSIZ,pipe_read_buff); } } break; } default: { free_buf(&sig); break; } } } }