0

I'm trying to write a C program that is able to test the performance of other programs by passing in input and testing the output without having to restart the program every time it runs. Co-workers and I are writing sudoku solvers, and I'm writing the program to test how fast each one runs by solving numerous puzzles, which could all be in different languages, and I don't want to penalize people for using languages, like Java, that are really slow to start up. Ideally, this program will start the sudoku solver program, keep it running, and continually pass in a new puzzle via stdin and test the output in stdout.

Here's pseudocode of what I want to do:

start a sudoku solver in another process
once process is running
    pass puzzle string into child stdin
    wait until output comes into stdout
    repeat until end time limit ends
close process

I've messed around with popen, but I couldn't figure out how to write to the child process stdin. I've done a bunch of poking around the internet, and I haven't been able to figure it out.

Any suggestions on how to accomplish this? I'm running this on a Linux box. It doesn't have to be stdin and stdout for communication, but that would be the easiest for everyone else.

EmptyArsenal
  • 7,314
  • 4
  • 33
  • 56
  • You need to spend a few weeks reading more about Unix programming, e.g. [ALP](http://www.cse.hcmut.edu.vn/~hungnq/courses/nap/alp.pdf) or some newer book. You basically want to understand how a shell works. Most [unix shells](https://en.wikipedia.org/wiki/Unix_shell) or batch processors are [free software](https://en.wikipedia.org/wiki/Free_software), so study their source code. But your question is too broad. – Basile Starynkevitch Mar 27 '18 at 04:22
  • You also need to define common conventions and protocols. Look also into `batch` command. – Basile Starynkevitch Mar 27 '18 at 04:25
  • Study [intro(2)](http://man7.org/linux/man-pages/man2/intro.2.html), [syscalls(2)](http://man7.org/linux/man-pages/man2/syscalls.2.html). In particular [fork(2)](http://man7.org/linux/man-pages/man2/fork.2.html), [pipe(2)](http://man7.org/linux/man-pages/man2/pipe.2.html), [execve(2)](http://man7.org/linux/man-pages/man2/execve.2.html), [poll(2)](http://man7.org/linux/man-pages/man2/poll.2.html), [waitpid(2)](http://man7.org/linux/man-pages/man2/waitpid.2.html) and more.. Read also more about OSes, e.g. [*Operating Systems: Three Easy Pieces*](http://pages.cs.wisc.edu/~remzi/OSTEP/) – Basile Starynkevitch Mar 27 '18 at 04:31
  • Note that the Sudoku solvers will have to be written so that they loop, solving problems while there is more input. If they're written to solve one problem, there's nothing you can sanely do to make the solve a second problem except by restarting them. – Jonathan Leffler Mar 27 '18 at 04:56
  • @JonathanLeffler The idea would be that you'd pass in a new line with a sudoku puzzle into stdin after getting a response. – EmptyArsenal Mar 27 '18 at 04:59
  • @EmptyArsenal: so you are defining a bit of protocol. Good. But document your protocols and conventions entirely. You could want some more structured protocol (e.g. perhaps using [JSON](http://json.org/), separated by newlines) – Basile Starynkevitch Mar 27 '18 at 05:04
  • You should look at this [question](https://stackoverflow.com/questions/17716359/redirect-child-processs-stdin-and-stdout-to-pipes) and use [`exec`](http://man7.org/linux/man-pages/man2/execve.2.html) family of functions after the `fork`. – Ajay Brahmakshatriya Mar 27 '18 at 05:36
  • I think you my just want `popen ()` – technosaurus Mar 27 '18 at 05:37
  • 1
    @technosaurus with [`popen`](http://man7.org/linux/man-pages/man3/popen.3.html) you only get a unidirectional pipe. – Ajay Brahmakshatriya Mar 27 '18 at 05:41
  • If you want to "cheat" and use the TCP/IP network stack instead, which may be easier than POSIX-specific IPC, you can pipe their programs to/from `netcat`. – sudo Mar 27 '18 at 07:05

1 Answers1

1

This is more a long comment than an answer, but your question is really too broad and ill-defined, and I'm just giving some hints.

You first need to understand how to start, manage, and communicate with child processes. An entire Unix programming book is needed to explain that. You could read ALP or some newer book. You need to be able to write a Unix shell-like program. Become familiar with many syscalls(2) including fork(2), pipe(2), execve(2), dup2(2), poll(2), waitpid(2) and a dozen others. See also signal(7) & time(7).

You also need to discuss with your colleagues some conventions and protocol about these sudoku programs and how your controlling program would communicate with them (and the evil is in the details). For example, your pseudo-code is mentioning "pass puzzle string" but you don't define what that exactly means (what if the string contains newlines, or weird characters?). Read also about inter-process communication.

(You might want to have more than one sudoku process running. You probably don't want a buggy sudoku client to break your controlling program. This is unclear in your question)

You could want to define a text-based protocol (they are simpler to debug and use than binary protocols). Details matter a lot, so document it precisely (probably using some EBNF notation). You might want to use textual formats like JSON, YAML, S-expressions. You could take inspiration from SMTP, HTTP, JSONRPC etc (or perhaps choose to use one of them).

Remember that pipe(7)-s, fifo(7)-s and tcp(7)-s socket(7)-s are just a stream of bytes without any message boundaries. Any message organization above these should be a documented convention (and it might happen that the message would be fragmented, so you need careful buffering). See also this.

(I recommend making some free software sample implementation of your protocol)

Look also into similar work, perhaps SAT competition (or chess contests programs, I don't know the details).

Read also something about OSes, like Operating Systems: Three Easy Pieces

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • Great answer. I will say, though, I didn't need a whole Unix programming book to do this (with my Hearts AI I was testing). Some Googling around about named pipes got me what I needed, but I already knew about message boundaries and had used TCP sockets before. – sudo Mar 27 '18 at 05:35
  • No, that won't be enough. You need at least to know half of [ALP](http://www.cse.hcmut.edu.vn/~hungnq/courses/nap/alp.pdf) and that is much too long to fit in an answer. In particular, you need to understand why [poll(2)](http://man7.org/linux/man-pages/man2/poll.2.html) is needed, and that takes several chapters of explanation. My last paragraph about pipes being just a stream of bytes is important. OP probably don't realize the "message boundary" thing – Basile Starynkevitch Mar 27 '18 at 05:36
  • @BasileStarynkevitch `poll` might not be really required if parent and the child agree on a input/output convention while passing size information carefully. – Ajay Brahmakshatriya Mar 27 '18 at 05:38
  • It depends what the OP really wants. His question is too broad and we can only make guesses – Basile Starynkevitch Mar 27 '18 at 05:39
  • 1
    If OP wants to handle the case of a buggy sudoku client (e.g. which loops indefinitely in outputting garbage or in waiting for input) he probably needs `poll` – Basile Starynkevitch Mar 27 '18 at 05:59