AbstractOperatingSystem.st
branchjv
changeset 19353 2b04ee017e72
parent 19225 9e8abf62f932
parent 19341 2ab29dd7ec1a
child 19431 3e697e4bcbf5
equal deleted inserted replaced
19333:b26c61158551 19353:2b04ee017e72
   907 !AbstractOperatingSystem class methodsFor:'executing OS commands-private'!
   907 !AbstractOperatingSystem class methodsFor:'executing OS commands-private'!
   908 
   908 
   909 shuffleAllFrom:anInStream to:anOutStream lineWise:lineWise lockWith:aLock
   909 shuffleAllFrom:anInStream to:anOutStream lineWise:lineWise lockWith:aLock
   910 
   910 
   911     lineWise ifFalse:[
   911     lineWise ifFalse:[
   912         ^ anInStream copyToEndInto:anOutStream.
   912 	^ anInStream copyToEndInto:anOutStream.
   913     ].
   913     ].
   914     [anInStream isOpen and:[anInStream atEnd not]] whileTrue:[
   914     [anInStream isOpen and:[anInStream atEnd not]] whileTrue:[
   915         aLock critical:[
   915 	aLock critical:[
   916             self
   916 	    self
   917                 shuffleFrom:anInStream
   917 		shuffleFrom:anInStream
   918                 to:anOutStream
   918 		to:anOutStream
   919                 lineWise:lineWise
   919 		lineWise:lineWise
   920         ]
   920 	]
   921     ]
   921     ]
   922 !
   922 !
   923 
   923 
   924 shuffleFrom:anInStream to:anOutStream lineWise:lineWise
   924 shuffleFrom:anInStream to:anOutStream lineWise:lineWise
   925     "copy data from anInStream to anOutStream.
   925     "copy data from anInStream to anOutStream.
  1337      closeStreams|
  1337      closeStreams|
  1338 
  1338 
  1339     terminateLock := Semaphore forMutualExclusion.
  1339     terminateLock := Semaphore forMutualExclusion.
  1340     ((externalInStream := anInStream) notNil
  1340     ((externalInStream := anInStream) notNil
  1341      and:[externalInStream isExternalStream not]) ifTrue:[
  1341      and:[externalInStream isExternalStream not]) ifTrue:[
  1342         pIn := NonPositionableExternalStream makePipe.
  1342 	pIn := NonPositionableExternalStream makePipe.
  1343         inStreamToClose := externalInStream := pIn at:1.
  1343 	inStreamToClose := externalInStream := pIn at:1.
  1344         shuffledInStream := pIn at:2.
  1344 	shuffledInStream := pIn at:2.
  1345         anInStream isBinary ifTrue:[
  1345 	anInStream isBinary ifTrue:[
  1346             shuffledInStream binary
  1346 	    shuffledInStream binary
  1347         ].
  1347 	].
  1348         lineWise ifFalse:[
  1348 	lineWise ifFalse:[
  1349             shuffledInStream blocking:false.
  1349 	    shuffledInStream blocking:false.
  1350         ].
  1350 	].
  1351 
  1351 
  1352         "/ start a reader process, shuffling data from the given
  1352 	"/ start a reader process, shuffling data from the given
  1353         "/ inStream to the pipe (which is connected to the commands input)
  1353 	"/ inStream to the pipe (which is connected to the commands input)
  1354         inputShufflerProcess :=
  1354 	inputShufflerProcess :=
  1355             [
  1355 	    [
  1356                 [
  1356 		[
  1357                     [anInStream atEnd] whileFalse:[
  1357 		    [anInStream atEnd] whileFalse:[
  1358                         self shuffleFrom:anInStream to:shuffledInStream lineWise:lineWise.
  1358 			self shuffleFrom:anInStream to:shuffledInStream lineWise:lineWise.
  1359                         shuffledInStream flush
  1359 			shuffledInStream flush
  1360                     ]
  1360 		    ]
  1361                 ] ensure:[
  1361 		] ensure:[
  1362                     shuffledInStream close
  1362 		    shuffledInStream close
  1363                 ]
  1363 		]
  1364             ] newProcess
  1364 	    ] newProcess
  1365                 name:'cmd input shuffler';
  1365 		name:'cmd input shuffler';
  1366 "/                beSystemProcess;
  1366 "/                beSystemProcess;
  1367                 resume.
  1367 		resume.
  1368     ].
  1368     ].
  1369     ((externalOutStream := anOutStream) notNil
  1369     ((externalOutStream := anOutStream) notNil
  1370      and:[externalOutStream isExternalStream not]) ifTrue:[
  1370      and:[externalOutStream isExternalStream not]) ifTrue:[
  1371         pOut := NonPositionableExternalStream makePipe.
  1371 	pOut := NonPositionableExternalStream makePipe.
  1372         shuffledOutStream := (pOut at:1).
  1372 	shuffledOutStream := (pOut at:1).
  1373         anOutStream isBinary ifTrue:[
  1373 	anOutStream isBinary ifTrue:[
  1374             shuffledOutStream binary
  1374 	    shuffledOutStream binary
  1375         ].
  1375 	].
  1376         outStreamToClose := externalOutStream := pOut at:2.
  1376 	outStreamToClose := externalOutStream := pOut at:2.
  1377         outputShufflerProcess :=
  1377 	outputShufflerProcess :=
  1378             [
  1378 	    [
  1379                 WriteError handle:[:ex |
  1379 		WriteError handle:[:ex |
  1380                     "/ ignored
  1380 		    "/ ignored
  1381                 ] do:[
  1381 		] do:[
  1382                     self shuffleAllFrom:shuffledOutStream to:anOutStream lineWise:lineWise lockWith:terminateLock.
  1382 		    self shuffleAllFrom:shuffledOutStream to:anOutStream lineWise:lineWise lockWith:terminateLock.
  1383                 ].
  1383 		].
  1384             ] newProcess
  1384 	    ] newProcess
  1385                 priority:(Processor userSchedulingPriority "+ 1");
  1385 		priority:(Processor userSchedulingPriority "+ 1");
  1386                 name:'cmd output shuffler';
  1386 		name:'cmd output shuffler';
  1387 "/                beSystemProcess;
  1387 "/                beSystemProcess;
  1388                 resume.
  1388 		resume.
  1389     ].
  1389     ].
  1390     (externalErrStream := anErrStream) notNil ifTrue:[
  1390     (externalErrStream := anErrStream) notNil ifTrue:[
  1391         anErrStream == anOutStream ifTrue:[
  1391 	anErrStream == anOutStream ifTrue:[
  1392             externalErrStream := externalOutStream
  1392 	    externalErrStream := externalOutStream
  1393         ] ifFalse:[
  1393 	] ifFalse:[
  1394             anErrStream isExternalStream ifFalse:[
  1394 	    anErrStream isExternalStream ifFalse:[
  1395                 pErr := NonPositionableExternalStream makePipe.
  1395 		pErr := NonPositionableExternalStream makePipe.
  1396                 shuffledErrStream := (pErr at:1).
  1396 		shuffledErrStream := (pErr at:1).
  1397                 anErrStream isBinary ifTrue:[
  1397 		anErrStream isBinary ifTrue:[
  1398                     shuffledErrStream binary
  1398 		    shuffledErrStream binary
  1399                 ].
  1399 		].
  1400                 errStreamToClose := externalErrStream := pErr at:2.
  1400 		errStreamToClose := externalErrStream := pErr at:2.
  1401                 errorShufflerProcess :=
  1401 		errorShufflerProcess :=
  1402                     [
  1402 		    [
  1403                         self shuffleAllFrom:shuffledErrStream to:anErrStream lineWise:lineWise lockWith:terminateLock.
  1403 			self shuffleAllFrom:shuffledErrStream to:anErrStream lineWise:lineWise lockWith:terminateLock.
  1404                     ] newProcess
  1404 		    ] newProcess
  1405                         priority:(Processor userSchedulingPriority + 1);
  1405 			priority:(Processor userSchedulingPriority + 1);
  1406                         name:'cmd err-output shuffler';
  1406 			name:'cmd err-output shuffler';
  1407 "/                        beSystemProcess;
  1407 "/                        beSystemProcess;
  1408                         resume.
  1408 			resume.
  1409             ]
  1409 	    ]
  1410         ]
  1410 	]
  1411     ].
  1411     ].
  1412     ((externalAuxStream := anAuxStream) notNil
  1412     ((externalAuxStream := anAuxStream) notNil
  1413      and:[externalAuxStream isExternalStream not]) ifTrue:[
  1413      and:[externalAuxStream isExternalStream not]) ifTrue:[
  1414         pAux := NonPositionableExternalStream makePipe.
  1414 	pAux := NonPositionableExternalStream makePipe.
  1415         auxStreamToClose := externalAuxStream := pAux at:1.
  1415 	auxStreamToClose := externalAuxStream := pAux at:1.
  1416         shuffledAuxStream := pAux at:2.
  1416 	shuffledAuxStream := pAux at:2.
  1417         shuffledAuxStream blocking:false.
  1417 	shuffledAuxStream blocking:false.
  1418         anAuxStream isBinary ifTrue:[
  1418 	anAuxStream isBinary ifTrue:[
  1419             shuffledAuxStream binary
  1419 	    shuffledAuxStream binary
  1420         ].
  1420 	].
  1421 
  1421 
  1422         "/ start a reader process, shuffling data from the given
  1422 	"/ start a reader process, shuffling data from the given
  1423         "/ auxStream to the pipe (which is connected to the commands aux)
  1423 	"/ auxStream to the pipe (which is connected to the commands aux)
  1424         auxShufflerProcess :=
  1424 	auxShufflerProcess :=
  1425             [
  1425 	    [
  1426                 [
  1426 		[
  1427                     [anAuxStream atEnd] whileFalse:[
  1427 		    [anAuxStream atEnd] whileFalse:[
  1428                         self shuffleFrom:anAuxStream to:shuffledAuxStream lineWise:false.
  1428 			self shuffleFrom:anAuxStream to:shuffledAuxStream lineWise:false.
  1429                         shuffledAuxStream flush
  1429 			shuffledAuxStream flush
  1430                     ]
  1430 		    ]
  1431                 ] ensure:[
  1431 		] ensure:[
  1432                     shuffledAuxStream close
  1432 		    shuffledAuxStream close
  1433                 ]
  1433 		]
  1434             ] newProcess
  1434 	    ] newProcess
  1435                 name:'cmd aux shuffler';
  1435 		name:'cmd aux shuffler';
  1436 "/                beSystemProcess;
  1436 "/                beSystemProcess;
  1437                 resume.
  1437 		resume.
  1438     ].
  1438     ].
  1439 
  1439 
  1440     stopShufflers := [:shuffleRest |
  1440     stopShufflers := [:shuffleRest |
  1441             inputShufflerProcess notNil ifTrue:[
  1441 	    inputShufflerProcess notNil ifTrue:[
  1442                 terminateLock critical:[inputShufflerProcess terminate].
  1442 		terminateLock critical:[inputShufflerProcess terminate].
  1443                 inputShufflerProcess waitUntilTerminated
  1443 		inputShufflerProcess waitUntilTerminated
  1444             ].
  1444 	    ].
  1445             auxShufflerProcess notNil ifTrue:[
  1445 	    auxShufflerProcess notNil ifTrue:[
  1446                 terminateLock critical:[auxShufflerProcess terminate].
  1446 		terminateLock critical:[auxShufflerProcess terminate].
  1447                 auxShufflerProcess waitUntilTerminated
  1447 		auxShufflerProcess waitUntilTerminated
  1448             ].
  1448 	    ].
  1449             outputShufflerProcess notNil ifTrue:[
  1449 	    outputShufflerProcess notNil ifTrue:[
  1450                 terminateLock critical:[outputShufflerProcess terminate].
  1450 		terminateLock critical:[outputShufflerProcess terminate].
  1451                 outputShufflerProcess waitUntilTerminated.
  1451 		outputShufflerProcess waitUntilTerminated.
  1452                 shuffleRest ifTrue:[ self shuffleRestFrom:shuffledOutStream to:anOutStream lineWise:lineWise ].
  1452 		shuffleRest ifTrue:[ self shuffleRestFrom:shuffledOutStream to:anOutStream lineWise:lineWise ].
  1453                 shuffledOutStream close.
  1453 		shuffledOutStream close.
  1454             ].
  1454 	    ].
  1455             errorShufflerProcess notNil ifTrue:[
  1455 	    errorShufflerProcess notNil ifTrue:[
  1456                 terminateLock critical:[errorShufflerProcess terminate].
  1456 		terminateLock critical:[errorShufflerProcess terminate].
  1457                 errorShufflerProcess waitUntilTerminated.
  1457 		errorShufflerProcess waitUntilTerminated.
  1458                 shuffleRest ifTrue:[ self shuffleRestFrom:shuffledErrStream to:anErrStream lineWise:lineWise ].
  1458 		shuffleRest ifTrue:[ self shuffleRestFrom:shuffledErrStream to:anErrStream lineWise:lineWise ].
  1459                 shuffledErrStream close.
  1459 		shuffledErrStream close.
  1460             ].
  1460 	    ].
  1461         ].
  1461 	].
  1462 
  1462 
  1463     closeStreams := [
  1463     closeStreams := [
  1464             inStreamToClose notNil ifTrue:[
  1464 	    inStreamToClose notNil ifTrue:[
  1465                 inStreamToClose close
  1465 		inStreamToClose close
  1466             ].
  1466 	    ].
  1467             errStreamToClose notNil ifTrue:[
  1467 	    errStreamToClose notNil ifTrue:[
  1468                 errStreamToClose close
  1468 		errStreamToClose close
  1469             ].
  1469 	    ].
  1470             outStreamToClose notNil ifTrue:[
  1470 	    outStreamToClose notNil ifTrue:[
  1471                 outStreamToClose close
  1471 		outStreamToClose close
  1472             ].
  1472 	    ].
  1473             auxStreamToClose notNil ifTrue:[
  1473 	    auxStreamToClose notNil ifTrue:[
  1474                 auxStreamToClose close
  1474 		auxStreamToClose close
  1475             ].
  1475 	    ].
  1476             nullStream notNil ifTrue:[
  1476 	    nullStream notNil ifTrue:[
  1477                 nullStream close
  1477 		nullStream close
  1478             ].
  1478 	    ].
  1479         ].
  1479 	].
  1480 
  1480 
  1481 
  1481 
  1482     sema := Semaphore new name:'OS command wait'.
  1482     sema := Semaphore new name:'OS command wait'.
  1483     [
  1483     [
  1484         externalInStream isNil ifTrue:[
  1484 	externalInStream isNil ifTrue:[
  1485             externalInStream := nullStream := Filename nullDevice readWriteStream.
  1485 	    externalInStream := nullStream := Filename nullDevice readWriteStream.
  1486         ].
  1486 	].
  1487         externalOutStream isNil ifTrue:[
  1487 	externalOutStream isNil ifTrue:[
  1488             nullStream isNil ifTrue:[nullStream := Filename nullDevice writeStream].
  1488 	    nullStream isNil ifTrue:[nullStream := Filename nullDevice writeStream].
  1489             externalOutStream := nullStream.
  1489 	    externalOutStream := nullStream.
  1490         ].
  1490 	].
  1491         externalErrStream isNil ifTrue:[
  1491 	externalErrStream isNil ifTrue:[
  1492             externalErrStream := externalOutStream
  1492 	    externalErrStream := externalOutStream
  1493         ].
  1493 	].
  1494 
  1494 
  1495         pid := Processor
  1495 	pid := Processor
  1496                     monitor:[
  1496 		    monitor:[
  1497                         self
  1497 			self
  1498                             startProcess:aCommandStringOrArray
  1498 			    startProcess:aCommandStringOrArray
  1499                             inputFrom:externalInStream
  1499 			    inputFrom:externalInStream
  1500                             outputTo:externalOutStream
  1500 			    outputTo:externalOutStream
  1501                             errorTo:externalErrStream
  1501 			    errorTo:externalErrStream
  1502                             auxFrom:externalAuxStream
  1502 			    auxFrom:externalAuxStream
  1503                             environment:environmentDictionary
  1503 			    environment:environmentDictionary
  1504                             inDirectory:dirOrNil
  1504 			    inDirectory:dirOrNil
  1505                     ]
  1505 		    ]
  1506                     action:[:status |
  1506 		    action:[:status |
  1507                         status stillAlive ifFalse:[
  1507 			status stillAlive ifFalse:[
  1508                             exitStatus := status.
  1508 			    exitStatus := status.
  1509                             sema signal.
  1509 			    sema signal.
  1510                             self closePid:pid
  1510 			    self closePid:pid
  1511                         ]
  1511 			]
  1512                     ].
  1512 		    ].
  1513 
  1513 
  1514         pid isNil ifTrue:[
  1514 	pid isNil ifTrue:[
  1515             exitStatus := self osProcessStatusClass processCreationFailure
  1515 	    exitStatus := self osProcessStatusClass processCreationFailure
  1516         ] ifFalse:[
  1516 	] ifFalse:[
  1517             sema wait.
  1517 	    sema wait.
  1518         ].
  1518 	].
  1519     ] ifCurtailed:[
  1519     ] ifCurtailed:[
  1520         closeStreams value.
  1520 	closeStreams value.
  1521         pid notNil ifTrue:[
  1521 	pid notNil ifTrue:[
  1522             "/ terminate the os-command (and all of its forked commands)
  1522 	    "/ terminate the os-command (and all of its forked commands)
  1523             self terminateProcessGroup:pid.
  1523 	    self terminateProcessGroup:pid.
  1524             self terminateProcess:pid.
  1524 	    self terminateProcess:pid.
  1525             self closePid:pid.
  1525 	    self closePid:pid.
  1526         ].
  1526 	].
  1527         stopShufflers value:false.
  1527 	stopShufflers value:false.
  1528     ].
  1528     ].
  1529 
  1529 
  1530     closeStreams value.
  1530     closeStreams value.
  1531     stopShufflers value:true.
  1531     stopShufflers value:true.
  1532     (exitStatus isNil or:[exitStatus success]) ifFalse:[
  1532     (exitStatus isNil or:[exitStatus success]) ifFalse:[
  1533         ^ aBlock value:exitStatus
  1533 	^ aBlock value:exitStatus
  1534     ].
  1534     ].
  1535     ^ true
  1535     ^ true
  1536 
  1536 
  1537     "
  1537     "
  1538         |outStream errStream|
  1538 	|outStream errStream|
  1539 
  1539 
  1540         outStream := '' writeStream.
  1540 	outStream := '' writeStream.
  1541 
  1541 
  1542         OperatingSystem executeCommand:'ls -l'
  1542 	OperatingSystem executeCommand:'ls -l'
  1543                         inputFrom:'abc' readStream
  1543 			inputFrom:'abc' readStream
  1544                         outputTo:outStream
  1544 			outputTo:outStream
  1545                         errorTo:nil
  1545 			errorTo:nil
  1546                         inDirectory:nil
  1546 			inDirectory:nil
  1547                         lineWise:true
  1547 			lineWise:true
  1548                         onError:[:exitStatus | ^ false].
  1548 			onError:[:exitStatus | ^ false].
  1549         outStream contents
  1549 	outStream contents
  1550     "
  1550     "
  1551 
  1551 
  1552     "
  1552     "
  1553         |outStream errStream|
  1553 	|outStream errStream|
  1554 
  1554 
  1555         outStream := #[] writeStream.
  1555 	outStream := #[] writeStream.
  1556 
  1556 
  1557         OperatingSystem executeCommand:'cat'
  1557 	OperatingSystem executeCommand:'cat'
  1558                         inputFrom:(ByteArray new:5000000) readStream
  1558 			inputFrom:(ByteArray new:5000000) readStream
  1559                         outputTo:outStream
  1559 			outputTo:outStream
  1560                         errorTo:nil
  1560 			errorTo:nil
  1561                         inDirectory:nil
  1561 			inDirectory:nil
  1562                         lineWise:false
  1562 			lineWise:false
  1563                         onError:[:exitStatus | ^ false].
  1563 			onError:[:exitStatus | ^ false].
  1564         outStream size
  1564 	outStream size
  1565     "
  1565     "
  1566 
  1566 
  1567     "
  1567     "
  1568         |outStream errStream|
  1568 	|outStream errStream|
  1569 
  1569 
  1570         outStream := '' writeStream.
  1570 	outStream := '' writeStream.
  1571 
  1571 
  1572         OperatingSystem executeCommand:'gpg -s --batch --no-tty --passphrase-fd 0 /tmp/passwd'
  1572 	OperatingSystem executeCommand:'gpg -s --batch --no-tty --passphrase-fd 0 /tmp/passwd'
  1573                         inputFrom:'bla' readStream
  1573 			inputFrom:'bla' readStream
  1574                         outputTo:outStream
  1574 			outputTo:outStream
  1575                         errorTo:nil
  1575 			errorTo:nil
  1576                         inDirectory:nil
  1576 			inDirectory:nil
  1577                         lineWise:true
  1577 			lineWise:true
  1578                         onError:[:exitStatus |  false].
  1578 			onError:[:exitStatus |  false].
  1579         outStream contents
  1579 	outStream contents
  1580     "
  1580     "
  1581 
  1581 
  1582     "Modified: / 11-02-2007 / 20:54:39 / cg"
  1582     "Modified: / 11-02-2007 / 20:54:39 / cg"
  1583 !
  1583 !
  1584 
  1584 
  6035 
  6035 
  6036 %{  /* NOCONTEXT */
  6036 %{  /* NOCONTEXT */
  6037     unsigned INT low, high;
  6037     unsigned INT low, high;
  6038 
  6038 
  6039 #ifdef __x86_64__
  6039 #ifdef __x86_64__
  6040 # if defined(__GCC__)
  6040 # if defined(__GCC__) || defined(__CLANG__) || defined(__MINGW64__)
  6041     asm volatile("rdtsc" : "=a"(low), "=d"(high));
  6041     asm volatile("rdtsc" : "=a"(low), "=d"(high));
  6042     RETURN ( __MKUINT(low + (high << 32)) );
  6042     RETURN ( __MKUINT(low + (high << 32)) );
  6043 # endif
  6043 # endif
  6044 #endif
  6044 #endif
  6045 
  6045 
  6051     __emit__(0x0F,0x31);            /* RDTSC instruction */
  6051     __emit__(0x0F,0x31);            /* RDTSC instruction */
  6052     _asm { mov low,eax };
  6052     _asm { mov low,eax };
  6053     _asm { mov high,edx };
  6053     _asm { mov high,edx };
  6054     _asm { pop edx };
  6054     _asm { pop edx };
  6055 # else
  6055 # else
  6056 #  if defined(__MINGW_H) || defined(__GNUC__)
  6056 #  if defined(__MINGW_H) || defined(__MINGW32__) || defined(__GNUC__)
  6057     asm volatile("rdtsc" : "=a"(low), "=d"(high));
  6057     asm volatile("rdtsc" : "=a"(low), "=d"(high));
  6058 #  else
  6058 #  else
  6059     goto unsupported;
  6059     goto unsupported;
  6060 #  endif
  6060 #  endif
  6061 # endif
  6061 # endif
  6781      be finished."
  6781      be finished."
  6782 
  6782 
  6783     |result fdArray|
  6783     |result fdArray|
  6784 
  6784 
  6785     self supportsSelect ifFalse:[
  6785     self supportsSelect ifFalse:[
  6786         "/ mhmh - what should we do then ?
  6786 	"/ mhmh - what should we do then ?
  6787         "/ For now, return true as if data was present,
  6787 	"/ For now, return true as if data was present,
  6788         "/ and let the thread fall into the write.
  6788 	"/ and let the thread fall into the write.
  6789         "/ It will then (hopefully) be desceduled there and
  6789 	"/ It will then (hopefully) be desceduled there and
  6790         "/ effectively polling for output.
  6790 	"/ effectively polling for output.
  6791         ^ true
  6791 	^ true
  6792     ].
  6792     ].
  6793 
  6793 
  6794     result := self
  6794     result := self
  6795                 selectOnAnyReadable:nil writable:(fdArray := Array with:fd) exception:fdArray
  6795 		selectOnAnyReadable:nil writable:(fdArray := Array with:fd) exception:fdArray
  6796                 readableInto:nil writableInto:nil exceptionInto:nil
  6796 		readableInto:nil writableInto:nil exceptionInto:nil
  6797                 withTimeOut:0.
  6797 		withTimeOut:0.
  6798 
  6798 
  6799     "on select error, a read will immediately return, so answer true"
  6799     "on select error, a read will immediately return, so answer true"
  6800     ^ result > 0.
  6800     ^ result > 0.
  6801 ! !
  6801 ! !
  6802 
  6802