Skip to content

Commit 6ac8faa

Browse files
committed
Merged
1 parent d2d7576 commit 6ac8faa

File tree

3 files changed

+554
-12
lines changed

3 files changed

+554
-12
lines changed
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package com.oracle.graal.python.test.module;
2+
3+
4+
import org.junit.Test;
5+
6+
import static com.oracle.graal.python.test.PythonTests.assertPrints;
7+
import static com.oracle.graal.python.test.PythonTests.runScript;
8+
9+
public class SubprocessTests {
10+
11+
@Test
12+
public void importSmokeTest(){
13+
String code = "import subprocess";
14+
15+
assertPrints("",code);
16+
}
17+
18+
19+
@Test
20+
public void lsSmokeTestRun(){
21+
String code = "import subprocess\n" +
22+
"n = subprocess.run([\"ls\",\"-a\"]) \n"+
23+
"print(n)";
24+
//assertPrints("",code);
25+
26+
runScript(new String[0],code,System.out,System.err);
27+
}
28+
29+
@Test
30+
public void lsTestCall(){
31+
String code = "import subprocess\n" +
32+
"n = subprocess.call([\"ls\",\"-a\"]) \n"+
33+
"print(n)";
34+
35+
//assertPrints("0\n",code);
36+
runScript(new String[0],code,System.out,System.err);
37+
}
38+
39+
40+
41+
42+
@Test
43+
public void pipeSmokeTest(){
44+
String code = "import os\n" +
45+
"os.pipe()\n";
46+
47+
runScript(new String[0],code,System.out,System.err);
48+
49+
}
50+
51+
52+
@Test
53+
public void envParamSmokeTest(){
54+
String code = "import subprocess\n" +
55+
"subprocess.run([\"ls\",\"-a\"], env={'test':'test'})";
56+
runScript(new String[0],code,System.out,System.err);
57+
}
58+
59+
60+
61+
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java

Lines changed: 261 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ protected void removeFile(int fd) {
200200
filePaths.set(fd, null);
201201
}
202202

203-
private static int nextFreeFd() {
203+
protected static int nextFreeFd() {
204204
for (int i = 0; i < filePaths.size(); i++) {
205205
String openPath = filePaths.get(i);
206206
if (openPath == null) {
@@ -1024,15 +1024,6 @@ private int getLength(PTuple times) {
10241024
}
10251025
}
10261026

1027-
@Builtin(name = "waitpid", fixedNumOfPositionalArgs = 2)
1028-
@GenerateNodeFactory
1029-
abstract static class WaitpidNode extends PythonBinaryBuiltinNode {
1030-
@SuppressWarnings("unused")
1031-
@Specialization
1032-
PTuple waitpid(int pid, int options) {
1033-
throw raise(NotImplementedError, "waitpid");
1034-
}
1035-
}
10361027

10371028
// FIXME: this is not nearly ready, just good enough for now
10381029
@Builtin(name = "system", fixedNumOfPositionalArgs = 1)
@@ -1200,4 +1191,264 @@ PBytes urandom(int size) {
12001191
return factory().createBytes(range);
12011192
}
12021193
}
1194+
1195+
1196+
1197+
@Builtin(name="WIFSIGNALED", fixedNumOfPositionalArgs = 1)
1198+
@GenerateNodeFactory
1199+
abstract static class WifsignaledNode extends PythonBuiltinNode{
1200+
1201+
/**
1202+
* Note: Implementation taken from glibc
1203+
* @param status
1204+
* @return
1205+
*/
1206+
@Specialization
1207+
@TruffleBoundary
1208+
boolean wifsignaled(int status){
1209+
return ((char) (((status)&0x7f)+1)>>1) >1;
1210+
}
1211+
}
1212+
1213+
@Builtin(name="WTERMSIG", fixedNumOfPositionalArgs = 1)
1214+
@GenerateNodeFactory
1215+
abstract static class WtermsigNode extends PythonBuiltinNode{
1216+
1217+
/**
1218+
* Note: Implementation taken from glibc
1219+
* @param status
1220+
* @return
1221+
*/
1222+
@Specialization
1223+
@TruffleBoundary
1224+
boolean wtermsig(int status){
1225+
return (status & 0x7f) != 0;
1226+
}
1227+
}
1228+
1229+
@Builtin(name="WIFEXITED", fixedNumOfPositionalArgs = 1)
1230+
@GenerateNodeFactory
1231+
abstract static class WifexitedNode extends PythonBuiltinNode{
1232+
/**
1233+
* Note: Implementation taken from glibc
1234+
* @param status
1235+
* @return
1236+
*/
1237+
@Specialization
1238+
@TruffleBoundary
1239+
boolean wifexited(int status){
1240+
return ((status) & 0x7f ) == 0;
1241+
}
1242+
}
1243+
1244+
1245+
@Builtin(name="WEXITSTATUS", fixedNumOfPositionalArgs = 1)
1246+
@GenerateNodeFactory
1247+
abstract static class WexitstatusNode extends PythonBuiltinNode{
1248+
1249+
/**
1250+
* Note: Implementation taken from glibc
1251+
* @param status
1252+
* @return
1253+
*/
1254+
@Specialization
1255+
@TruffleBoundary
1256+
boolean wexitstatus(int status){
1257+
return ((status & 0xFF00) >> 8) != 0;
1258+
}
1259+
}
1260+
1261+
1262+
1263+
@Builtin(name="WIFSTOPPED", fixedNumOfPositionalArgs = 1)
1264+
@GenerateNodeFactory
1265+
abstract static class WifstoppedNode extends PythonBuiltinNode{
1266+
/**
1267+
* Note: Implementation taken from glibc
1268+
* @param status
1269+
* @return
1270+
*/
1271+
@Specialization
1272+
@TruffleBoundary
1273+
boolean wifstopped(int status){
1274+
return (status & 0xff)== 0x7f;
1275+
}
1276+
}
1277+
1278+
@Builtin(name="WSTOPSIG", fixedNumOfPositionalArgs = 1)
1279+
@GenerateNodeFactory
1280+
abstract static class WstopsigNode extends PythonBuiltinNode{
1281+
/**
1282+
* Note: Implementation taken from glibc
1283+
* @param status
1284+
* @return
1285+
*/
1286+
@Specialization
1287+
@TruffleBoundary
1288+
boolean wstopsig(int status){
1289+
return ((status & 0xFF00) >> 8) != 0;
1290+
}
1291+
}
1292+
1293+
@Builtin(name="waitpid", fixedNumOfPositionalArgs = 2)
1294+
@GenerateNodeFactory
1295+
abstract static class WaitpidNode extends PythonBuiltinNode{
1296+
@Specialization
1297+
@TruffleBoundary
1298+
PTuple waitpid(long pid, int options){
1299+
1300+
//TODO check what is really needed
1301+
if(pid < -1){
1302+
//wait for any chlid process whose process group id is equal to the value of pid
1303+
throw raise(PythonErrorType.NotImplementedError, "Not implemented for pid <= 1");
1304+
}else if(pid == -1){
1305+
//wait for any child process
1306+
throw raise(PythonErrorType.NotImplementedError, "Not implemented for pid == -1");
1307+
}else if(pid == 0){
1308+
//wait for any child process whose process group id is equal to the value of the calling process
1309+
throw raise(PythonErrorType.NotImplementedError, "Not implemented for pid == 0");
1310+
}else{
1311+
//pid > 0 wait for the child process with this pid
1312+
1313+
//TODO consider possible options: WNOHANG, WUNTRACED and WCONTINUED
1314+
// seems like only WNOHANG is needed?
1315+
1316+
Process p = PosixSubprocessModuleBuiltins.getProcessByPid(pid);
1317+
int status = -1;
1318+
try {
1319+
status = p.waitFor();
1320+
1321+
//TODO: Make sure that here is the right place
1322+
PosixSubprocessModuleBuiltins.removeProcessByPid(pid);
1323+
1324+
} catch (InterruptedException e) {
1325+
//TODO: Error handling
1326+
e.printStackTrace();
1327+
throw raise(PythonErrorType.NotImplementedError, "Error handling for waitFor not implemented");
1328+
}
1329+
1330+
1331+
1332+
//TODO encode status return the right way
1333+
return factory().createTuple(new Object[]{
1334+
PosixSubprocessModuleBuiltins.getPidOfProcess(p), status});
1335+
}
1336+
}
1337+
}
1338+
1339+
/**
1340+
* taken from glibc:
1341+
*
1342+
*
1343+
* Bits in the third argument to 'waitpid'
1344+
* WNOHANG: Dont block waiting
1345+
*/
1346+
@Builtin(name="WNOHANG", fixedNumOfPositionalArgs = 1)
1347+
@GenerateNodeFactory
1348+
abstract static class WnohangNode extends PythonBuiltinNode{
1349+
@Specialization
1350+
@TruffleBoundary
1351+
int wnohang(){
1352+
return 1;
1353+
}
1354+
}
1355+
1356+
@SuppressWarnings("MagicConstant")
1357+
@Builtin(name="pipe", fixedNumOfPositionalArgs = 0)
1358+
@GenerateNodeFactory
1359+
abstract static class PipeNode extends PythonFileNode{
1360+
1361+
/*TODO find good (already existing?) implementation
1362+
Looks like there is no good implementation in java
1363+
for in-memory files that implement SeekableByteChannel?
1364+
*/
1365+
private class SeekableByteBuffer implements SeekableByteChannel{
1366+
1367+
ByteBuffer buffer;
1368+
1369+
private long position;
1370+
private boolean open;
1371+
public SeekableByteBuffer(ByteBuffer buffer){
1372+
this.buffer = buffer;
1373+
open = true;
1374+
}
1375+
1376+
@Override
1377+
public int read(ByteBuffer dst) throws IOException {
1378+
if(!isOpen()){
1379+
return -1;
1380+
}
1381+
1382+
int i = 0;
1383+
dst.reset();
1384+
1385+
while(dst.remaining() > 0 && buffer.remaining() > 0){
1386+
byte b = buffer.get();
1387+
dst.put(b);
1388+
i++;
1389+
}
1390+
1391+
return i;
1392+
}
1393+
1394+
@Override
1395+
public int write(ByteBuffer src) throws IOException {
1396+
1397+
int before = buffer.position();
1398+
buffer.put(src);
1399+
return buffer.position()-before;
1400+
}
1401+
1402+
@Override
1403+
public long position() throws IOException {
1404+
return buffer.position();
1405+
}
1406+
1407+
@Override
1408+
public SeekableByteChannel position(long newPosition) throws IOException {
1409+
//seeking not allowed in pipes...
1410+
throw new UnsupportedOperationException();
1411+
}
1412+
1413+
@Override
1414+
public long size() throws IOException {
1415+
return buffer.position();
1416+
}
1417+
1418+
@Override
1419+
public SeekableByteChannel truncate(long size) throws IOException {
1420+
throw new UnsupportedOperationException();
1421+
}
1422+
1423+
@Override
1424+
public boolean isOpen() {
1425+
return open;
1426+
}
1427+
1428+
@Override
1429+
public void close() throws IOException {
1430+
open = false;
1431+
}
1432+
}
1433+
1434+
@Specialization
1435+
@TruffleBoundary
1436+
Object pipe(){
1437+
1438+
ByteBuffer buffer = ByteBuffer.allocate(1024);
1439+
SeekableByteBuffer p = new SeekableByteBuffer(buffer);
1440+
1441+
int a = nextFreeFd();
1442+
files.set(a,p);
1443+
filePaths.set(a,"pipe");
1444+
1445+
int b = nextFreeFd();
1446+
files.set(b,p);
1447+
filePaths.set(b,"pipe");
1448+
1449+
return factory().createTuple(new Object[]{a,b});
1450+
}
1451+
1452+
}
1453+
12031454
}

0 commit comments

Comments
 (0)