Belle II Software development
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
20extern "C" {
21#include <nsm2/nsmlib2.h>
22#include <nsm2/nsmsys2.h>
23}
24
25using namespace std;
26using 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
34RFProcessManager::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
46RFProcessManager::~RFProcessManager()
47{
48}
49
50void RFProcessManager::signal_handler(int /*num*/)
51{
52}
53
54
55int 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
106int 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
147int 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
207int RFProcessManager::GetFd()
208{
209 return m_iopipe[0];
210}
211
212pid_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
int Execute(char *script, int nargs, char **args)
Abstract base class for different kinds of events.
STL namespace.