Belle II Software  release-08-01-10
RFProcessManager.cc
1 /**************************************************************************
2  * basf2 (Belle II Analysis Software Framework) *
3  * Author: The Belle II Collaboration *
4  * *
5  * See git log for contributors and copyright holders. *
6  * This file is licensed under LGPL-3.0, see LICENSE.md. *
7  **************************************************************************/
8 
9 #include "daq/rfarm/manager/RFProcessManager.h"
10 #include "daq/rfarm/manager/RFNSM.h"
11 
12 #include <fcntl.h>
13 #include <stdio.h>
14 #include <sys/types.h>
15 #include <sys/wait.h>
16 #include <unistd.h>
17 
18 #include <cstring>
19 
20 extern "C" {
21 #include <nsm2/nsmlib2.h>
22 #include <nsm2/nsmsys2.h>
23 }
24 
25 using namespace std;
26 using namespace Belle2;
27 
28 // Constructor/Destructor
29 
30 // *** OLD ***
31 //RFProcessManager::RFProcessManager( string& nodename, string& conffile, string& infofile ) :
32 // RFSharedMem (nodename.c_str()), RFNSM (nodename.c_str(), infofile.c_str() ), RFConf ( conffile.c_str() )
33 
34 RFProcessManager::RFProcessManager(char* /*nodename*/)
35 {
36  // Create IO pipe for output logging
37  if (pipe2(m_iopipe, O_NONBLOCK) < 0) {
38  perror("pipe");
39  m_iopipe[0] = -1; m_iopipe[1] = -1;
40  }
41  FILE* f = fopen("pid.data", "w");
42  fprintf(f, "%d", getpid());
43  fclose(f);
44 }
45 
46 RFProcessManager::~RFProcessManager()
47 {
48 }
49 
50 void RFProcessManager::signal_handler(int /*num*/)
51 {
52 }
53 
54 
55 int RFProcessManager::Execute(char* scr, int nargs, char** args)
56 {
57 
58  printf("RFProcessManager : Execute : scr=%s, nargs=%d\n", scr, nargs);
59  // Fork processes
60  pid_t pid = fork();
61  if (pid == (pid_t) 0) { // In case of forked process
62  char argbuf[10][256];
63  char* argval[10];
64  int nargval = 0;
66  strcpy(argbuf[0], scr);
67  argval[nargval++] = argbuf[0];
68  // Fill argbuf
69  for (int i = 0; i < nargs; i++) {
70  strcpy(argbuf[nargval], args[i]);
71  argval[nargval] = argbuf[nargval];
72  nargval++;
73  // printf ( "argval[%d] = %s\n", i+1, argval[i+1] );
74  }
75  argval[nargval] = NULL;
76 
77  // Connect stderr/out to write pipe[1], which is read by parent process thru pipe[0]
78  close(1);
79  dup2(m_iopipe[1], 1); // redirect stderr to pipe 1
80  close(2);
81  dup2(m_iopipe[1], 2); // redirect stdout to pipe 1
82  close(m_iopipe[0]); // Close read pipe in child process
83 
84  // execute script in forked process by execvp()
85  printf("RFProcessManager : invoking %s\n", scr);
86  for (int i = 0; i < 10; i++) {
87  if (argval[i] == NULL) break;
88  printf("argval[%d] = %s\n", i, argval[i]);
89  }
90  fflush(stdout);
91  fflush(stderr);
92  execvp(scr, argval); // returns int stexe
93  perror("execvp!!");
94  fprintf(stderr, "missing file : %s\n", scr);
95  fflush(stderr);
96  exit(-1);
97  }
98  // Parent process (pid>0 : success, pid<0 : error )
99  printf("RFProcessManager : forked. pid=%d\n", pid);
100  //close(m_iopipe[1]);
101 
102  m_pidlist.push_back(pid);
103  return pid;
104 }
105 
106 int RFProcessManager::Execute(char* scr,
107  char* arg0, char* arg1, char* arg2, char* arg3,
108  char* arg4, char* arg5, char* arg6, char* arg7)
109 {
110  char* arglist[8];
111  int narg = 0;
112  if (arg0 != NULL) {
113  arglist[0] = arg0;
114  narg++;
115  }
116  if (arg1 != NULL) {
117  arglist[1] = arg1;
118  narg++;
119  }
120  if (arg2 != NULL) {
121  arglist[2] = arg2;
122  narg++;
123  }
124  if (arg3 != NULL) {
125  arglist[3] = arg3;
126  narg++;
127  }
128  if (arg4 != NULL) {
129  arglist[4] = arg4;
130  narg++;
131  }
132  if (arg5 != NULL) {
133  arglist[5] = arg5;
134  narg++;
135  }
136  if (arg6 != NULL) {
137  arglist[6] = arg6;
138  narg++;
139  }
140  if (arg7 != NULL) {
141  arglist[7] = arg7;
142  narg++;
143  }
144  return Execute(scr, narg, arglist);
145 }
146 
147 int RFProcessManager::CheckOutput()
148 {
149  // Setup select parameter
150  fd_set fdset;
151 
152  // Fetch fd
153  int nfd;
154  for (;;) {
155  FD_ZERO(&fdset);
156  int highest = 0;
157  if (m_iopipe[0] > 0) {
158  FD_SET(m_iopipe[0], &fdset);
159  highest = m_iopipe[0];
160  } else {
161  printf("Pipe for log is not availablle\n");
162  }
163  NSMcontext* nsmc = RFNSM::GetContext();
164  if (nsmc) {
165  if (nsmc->sock > highest) highest = nsmc->sock;
166  FD_SET(nsmc->sock, &fdset);
167  } else {
168  //printf("No NSM context is available\n");
169  }
170  // Time out parameter
171  struct timeval tv;
172  tv.tv_sec = 1;
173  tv.tv_usec = 1; // omajinai
174 
175  if ((nfd = select(highest + 1, &fdset, NULL, NULL, &tv)) < 0) {
176  switch (errno) {
177  case EINTR: continue; // why? if we get a signal, we can return, too
178  case EAGAIN: continue;
179  default:
180  //close(m_iopipe[0]);
181  //m_iopipe[0] = -1;
182  return 0;
183  }
184  } else {
185  if (nsmc && FD_ISSET(nsmc->sock, &fdset)) {
186  // NSMCommunicator(nsmc).callContext();
187  char buf[NSM_TCPMSGSIZ];
188  if (nsmlib_recv(nsmc, (struct NSMtcphead_struct*)buf, 1000) < 0)
189  printf("RFProcessManager: Failed to read NSM context\n");
190  else
191  nsmlib_call(nsmc, (struct NSMtcphead_struct*)buf);
192  }
193  if (m_iopipe[0] > 0 &&
194  FD_ISSET(m_iopipe[0], &fdset)) {
195  break;
196  }
197  if (nfd == 0) break; // was a timeout -> return to do other stuff
198  }
199  }
200  // Return nfd
201  // time_t now = time ( NULL );
202  // printf ( "[%s] CheckOutput : nfd = %d\n", ctime(&now), nfd );
203  // fflush ( stdout );
204  return nfd;
205 }
206 
207 int RFProcessManager::GetFd()
208 {
209  return m_iopipe[0];
210 }
211 
212 pid_t RFProcessManager::CheckProcess()
213 {
214  for (vector<pid_t>::iterator it = m_pidlist.begin(); it != m_pidlist.end(); ++it) {
215  pid_t pid = *it;
216  int status;
217  pid_t outpid = waitpid(pid, &status, WNOHANG);
218  // if (outpid == -1) {
219  if (outpid != 0 || outpid == pid) {
220  m_pidlist.erase(it);
221  return pid;
222  }
223  }
224  return 0;
225 }
226 
Abstract base class for different kinds of events.