Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
IOHandler.cxx
Go to the documentation of this file.
1// Author: Danilo Piparo, Omar Zapata, Enric Tejedor 16/12/2015
2
3/*************************************************************************
4 * Copyright (C) 1995-2020, Rene Brun and Fons Rademakers. *
5 * All rights reserved. *
6 * *
7 * For the licensing terms see $ROOTSYS/LICENSE. *
8 * For the list of contributors see $ROOTSYS/README/CREDITS. *
9 *************************************************************************/
10
11#include <Python.h>
12
13#include <fcntl.h>
14#ifdef _MSC_VER // Visual Studio
15#include <winsock2.h>
16#include <io.h>
17#pragma comment(lib, "Ws2_32.lib")
18#define pipe(fds) _pipe(fds, 1048575, _O_BINARY)
19#define read _read
20#define dup _dup
21#define dup2 _dup2
22#define STDIN_FILENO 0
23#define STDOUT_FILENO 1
24#define STDERR_FILENO 2
25#else
26#include <unistd.h>
27#endif
28#include <cstdlib>
29#include <string>
30#include <iostream>
31#include "TClassEdit.h"
32#include "TError.h"
33#include "TInterpreter.h"
34
35//////////////////////////
36// MODULE FUNCTIONALITY //
37//////////////////////////
38
40private:
41 bool fCapturing = false;
42 std::string fStdoutpipe;
43 std::string fStderrpipe;
44 int fStdout_pipe[2] = {0, 0};
45 int fStderr_pipe[2] = {0, 0};
48
49public:
51 void Poll();
52 void InitCapture();
53 void EndCapture();
54 void Clear();
55 std::string &GetStdout();
56 std::string &GetStderr();
57};
58
59#ifndef F_LINUX_SPECIFIC_BASE
60#define F_LINUX_SPECIFIC_BASE 1024
61#endif
62#ifndef F_SETPIPE_SZ
63#define F_SETPIPE_SZ (F_LINUX_SPECIFIC_BASE + 7)
64#endif
65
66constexpr long MAX_PIPE_SIZE = 1048575;
67
69
70static void PollImpl(FILE *stdStream, int *pipeHandle, std::string &pipeContent)
71{
73#ifdef _MSC_VER
74 char buffer[60000] = "";
75 struct _stat st;
76 _fstat(pipeHandle[0], &st);
77 if (st.st_size) {
78 _read(pipeHandle[0], buffer, 60000);
79 pipeContent += buffer;
80 }
81#else
82 int buf_read;
83 char ch;
84 while (true) {
85 buf_read = read(pipeHandle[0], &ch, 1);
86 if (buf_read == 1) {
87 pipeContent += ch;
88 } else
89 break;
90 }
91#endif
92}
93
99
101{
103 if (pipe(pipeHandle) != 0) {
104 return;
105 }
106#ifndef _MSC_VER
108 if (flags_stdout == -1)
109 return;
113#endif
115}
116
125
127{
128 if (fCapturing) {
129 Poll();
132 close(fSaved_stdout);
133 close(fSaved_stderr);
134 close(fStdout_pipe[0]);
135 close(fStdout_pipe[1]);
136 close(fStderr_pipe[0]);
137 close(fStderr_pipe[1]);
138 fCapturing = false;
139 }
140}
141
143{
144 fStdoutpipe = "";
145 fStderrpipe = "";
146}
147
149{
150 return fStdoutpipe;
151}
152
154{
155 return fStderrpipe;
156}
157
159
160// Report exceptions that escape the interpreted code like TRint does at the
161// ROOT prompt (see TRint::HandleTermInput), instead of swallowing them
162// silently (ROOT-10589).
163static void ReportCaughtException(const char *location, const std::exception &e)
164{
165 int err = 0;
167 const char *demangledType = err ? "<UNKNOWN>" : demangledType_c;
168 ::Error(location, "%s caught: %s", demangledType, e.what());
170}
171
172bool JupyROOTExecutorImpl(const char *code)
173{
174 auto status = false;
175 try {
176 auto err = TInterpreter::kNoError;
177 if (gInterpreter->ProcessLine(code, &err)) {
178 status = true;
179 }
180
181 if (err == TInterpreter::kProcessing) {
182 gInterpreter->ProcessLine(".@");
183 gInterpreter->ProcessLine("cerr << \"Unbalanced braces. This cell was not processed.\" << endl;");
184 }
185 } catch (std::exception &e) {
186 ReportCaughtException("JupyROOTExecutor", e);
187 } catch (...) {
188 ::Error("JupyROOTExecutor", "Exception caught!");
189 }
190
191 return status;
192}
193
194bool JupyROOTDeclarerImpl(const char *code)
195{
196 auto status = false;
197 try {
198 if (gInterpreter->Declare(code)) {
199 status = true;
200 }
201 } catch (std::exception &e) {
202 ReportCaughtException("JupyROOTDeclarer", e);
203 } catch (...) {
204 ::Error("JupyROOTDeclarer", "Exception caught!");
205 }
206 return status;
207}
208
210{
211 const char *code;
212 if (!PyArg_ParseTuple(args, "s", &code))
213 return NULL;
214
215 auto res = JupyROOTExecutorImpl(code);
216
217 return PyLong_FromLong(res);
218}
219
221{
222 const char *code;
223 if (!PyArg_ParseTuple(args, "s", &code))
224 return NULL;
225
226 auto res = JupyROOTDeclarerImpl(code);
227
228 return PyLong_FromLong(res);
229}
230
236
238{
241 // Fixes for ROOT-7999
242 gInterpreter->ProcessLine("SetErrorHandler((ErrorHandlerFunc_t)&DefaultErrorHandler);");
243 }
244
246}
247
253
259
265
267{
268 auto out = JupyROOTExecutorHandler_ptr->GetStdout().c_str();
269 return PyUnicode_FromString(out);
270}
271
273{
274 auto err = JupyROOTExecutorHandler_ptr->GetStderr().c_str();
275 return PyUnicode_FromString(err);
276}
277
#define Py_RETURN_NONE
Definition CPyCppyy.h:268
free(fBuffer)
PyObject * JupyROOTExecutorHandler_Ctor(PyObject *, PyObject *)
static void ReportCaughtException(const char *location, const std::exception &e)
PyObject * JupyROOTDeclarer(PyObject *, PyObject *args)
static void InitCaptureImpl(int &savedStdStream, int *pipeHandle, int FILENO)
JupyROOTExecutorHandler * JupyROOTExecutorHandler_ptr
constexpr long MAX_PIPE_SIZE
Definition IOHandler.cxx:66
PyObject * JupyROOTExecutorHandler_GetStdout(PyObject *, PyObject *)
#define F_SETPIPE_SZ
Definition IOHandler.cxx:63
bool JupyROOTDeclarerImpl(const char *code)
static void PollImpl(FILE *stdStream, int *pipeHandle, std::string &pipeContent)
Definition IOHandler.cxx:70
bool JupyROOTExecutorImpl(const char *code)
PyObject * JupyROOTExecutor(PyObject *, PyObject *args)
PyObject * JupyROOTExecutorHandler_EndCapture(PyObject *, PyObject *)
PyObject * JupyROOTExecutorHandler_Poll(PyObject *, PyObject *)
PyObject * JupyROOTExecutorHandler_Clear(PyObject *, PyObject *)
PyObject * JupyROOTExecutorHandler_GetStderr(PyObject *, PyObject *)
PyObject * JupyROOTExecutorHandler_InitCapture(PyObject *, PyObject *)
PyObject * JupyROOTExecutorHandler_Dtor(PyObject *, PyObject *)
_object PyObject
#define e(i)
Definition RSha256.hxx:103
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
Definition TError.cxx:208
#define gInterpreter
std::string & GetStderr()
std::string & GetStdout()
char * DemangleTypeIdName(const std::type_info &ti, int &errorCode)
Demangle in a portable way the type id name.