Skip to content

Commit fd8e5ed

Browse files
committed
implement openpipe on parrot+windows
1 parent 4019ecc commit fd8e5ed

File tree

3 files changed

+102
-9
lines changed

3 files changed

+102
-9
lines changed

src/vm/parrot/ops/nqp.ops

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -565,6 +565,97 @@ static char *create_command_line(const char *const *args) {
565565
return cmd;
566566
}
567567

568+
static PIOHANDLE Run_OS_Command_Piped(PARROT_INTERP, PMC *command, PMC *env_hash, INTVAL flags,
569+
INTVAL *pid, INTVAL *status) {
570+
HANDLE current = GetCurrentProcess();
571+
HANDLE hnull = INVALID_HANDLE_VALUE;
572+
HANDLE hread = INVALID_HANDLE_VALUE;
573+
HANDLE hwrite = INVALID_HANDLE_VALUE;
574+
HANDLE hchild = INVALID_HANDLE_VALUE;
575+
STARTUPINFO si;
576+
PROCESS_INFORMATION pi;
577+
SECURITY_ATTRIBUTES sec;
578+
const char *env = pack_env_hash(interp, env_hash);
579+
const char *const *argv = pack_arg_array(interp, command);
580+
const char *cmd = create_command_line(argv);
581+
PIOHANDLE os_handle;
582+
583+
pi.hThread = INVALID_HANDLE_VALUE;
584+
pi.hProcess = INVALID_HANDLE_VALUE;
585+
sec.nLength = sizeof sec;
586+
sec.lpSecurityDescriptor = NULL;
587+
sec.bInheritHandle = TRUE;
588+
589+
si.cb = sizeof si;
590+
GetStartupInfo(&si);
591+
si.dwFlags = STARTF_USESTDHANDLES;
592+
if (CreatePipe(&hread, &hwrite, NULL, 0) == 0)
593+
goto fail;
594+
if (DuplicateHandle(current, flags & PARROT_EXEC_STDOUT ? hwrite : hread,
595+
current, &hchild,
596+
0, TRUE,
597+
DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)
598+
== 0)
599+
goto fail;
600+
if (hchild == INVALID_HANDLE_VALUE)
601+
goto fail;
602+
603+
if (flags & PARROT_EXEC_STDOUT) {
604+
/* Redirect input to NULL. This is to avoid
605+
* interferences in case both the child and
606+
* the parent tries to read from stdin.
607+
* May be unnecessary or even interfere
608+
* with valid usages, need more feedback. */
609+
hnull = CreateFile("NUL", GENERIC_READ|GENERIC_WRITE,
610+
0, &sec, OPEN_EXISTING,
611+
FILE_ATTRIBUTE_NORMAL, NULL);
612+
if (hnull == INVALID_HANDLE_VALUE)
613+
goto fail;
614+
si.hStdInput = hnull;
615+
si.hStdOutput = hchild;
616+
si.hStdError = hchild;
617+
}
618+
else {
619+
si.hStdInput = hchild;
620+
}
621+
622+
if (CreateProcess(NULL, cmd, NULL, NULL, TRUE, 0, env, NULL, &si, &pi) == 0)
623+
goto fail;
624+
625+
if (flags & PARROT_EXEC_STDOUT) {
626+
os_handle = hread;
627+
CloseHandle(hwrite);
628+
}
629+
else {
630+
os_handle = hwrite;
631+
CloseHandle(hread);
632+
}
633+
634+
Parrot_str_free_cstring(cmd);
635+
CloseHandle(pi.hThread);
636+
637+
*pid = (INTVAL)pi.hProcess;
638+
639+
return os_handle;
640+
641+
fail:
642+
if (cmd != NULL)
643+
Parrot_str_free_cstring(cmd);
644+
if (hnull != INVALID_HANDLE_VALUE)
645+
CloseHandle(hnull);
646+
if (hread != INVALID_HANDLE_VALUE)
647+
CloseHandle(hread);
648+
if (hwrite != INVALID_HANDLE_VALUE)
649+
CloseHandle(hwrite);
650+
if (hchild != INVALID_HANDLE_VALUE)
651+
CloseHandle(hchild);
652+
if (pi.hThread != INVALID_HANDLE_VALUE)
653+
CloseHandle(pi.hThread);
654+
if (pi.hProcess != INVALID_HANDLE_VALUE)
655+
CloseHandle(pi.hProcess);
656+
Parrot_ex_throw_from_c_noargs(interp, EXCEPTION_UNIMPLEMENTED,
657+
"pipe open error");
658+
}
568659
static INTVAL Run_OS_Command(PARROT_INTERP, PMC *command, PMC *env_hash)
569660
{
570661
DWORD status = 0;

t/nqp/86-pipes.t

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,11 @@ plan(14);
1919
ok( nqp::defined($q) == 1, 'nqp::openpipe nonexistent cmd');
2020

2121
my $qstr := nqp::readallfh($q);
22-
nqp::getcomp('nqp').backend.name eq 'moar'
23-
?? ok( $qstr eq '', 'nqp::readallfh with a pipe nonexistent command')
24-
!! ok( $qstr ~~ / 'not found' | 'not recognized' /, 'nqp::readallfh with a pipe nonexistent command');
25-
22+
nqp::getcomp('nqp').backend.name eq 'moar' ??
23+
ok( $qstr eq '', 'nqp::readallfh with a pipe nonexistent command') !!
24+
nqp::getcomp('nqp').backend.name eq 'parrot' ??
25+
ok( $qstr ~~ / 'doesnotexist' /, 'nqp::readallfh with a pipe nonexistent command') !!
26+
ok( $qstr ~~ / 'not found' | 'not recognized' /, 'nqp::readallfh with a pipe nonexistent command');
2627

2728
nqp::closefh($q); ok( 1, 'nqp::closefh with a pipe nonexistent command');
2829
}
@@ -42,10 +43,11 @@ plan(14);
4243
ok( nqp::defined($q) == 1, 'nqp::openpipe nonexistent cmd');
4344

4445
my $qstr := nqp::readallfh($q);
45-
nqp::getcomp('nqp').backend.name eq 'moar'
46-
?? ok( $qstr eq '', 'nqp::readallfh with a pipe nonexistent command')
47-
!! ok( $qstr ~~ / 'not found' | 'not recognized' /, 'nqp::readallfh with a pipe nonexistent command');
48-
46+
nqp::getcomp('nqp').backend.name eq 'moar' ??
47+
ok( $qstr eq '', 'nqp::readallfh with a pipe nonexistent command') !!
48+
nqp::getcomp('nqp').backend.name eq 'parrot' ??
49+
ok( $qstr ~~ / 'doesnotexist' /, 'nqp::readallfh with a pipe nonexistent command') !!
50+
ok( $qstr ~~ / 'not found' | 'not recognized' /, 'nqp::readallfh with a pipe nonexistent command');
4951

5052
ok( nqp::closefh_i($q) != 0, 'nqp::closefh_i with a pipe nonexistent command');
5153
}

tools/build/PARROT_REVISION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
RELEASE_6_9_0-81-g6d8687c
1+
RELEASE_6_9_0-123-g17e3545

0 commit comments

Comments
 (0)