Mercurial > hg > Members > aka > jupyter_CbC_kernel
annotate c_kernel/kernel.py @ 4:5c4b5066fab0
Do not try to execute the executable if compilation failed
author | Brendan Rius <brendan@omixy.com> |
---|---|
date | Fri, 25 Mar 2016 14:25:29 +0000 |
parents | 8ddfdd2a8574 |
children | aa54c85303b6 |
rev | line source |
---|---|
0 | 1 from ipykernel.kernelbase import Kernel |
2 import subprocess | |
3 import tempfile | |
2
b46b2e5b6c08
Improve error management by separating stdout and stderr
Brendan Rius <brendan@omixy.com>
parents:
0
diff
changeset
|
4 import os |
0 | 5 |
6 | |
7 class CKernel(Kernel): | |
8 implementation = 'c_kernel' | |
9 implementation_version = '1.0' | |
10 language = 'c' | |
11 language_version = 'C11' | |
2
b46b2e5b6c08
Improve error management by separating stdout and stderr
Brendan Rius <brendan@omixy.com>
parents:
0
diff
changeset
|
12 language_info = {'name': 'c', |
b46b2e5b6c08
Improve error management by separating stdout and stderr
Brendan Rius <brendan@omixy.com>
parents:
0
diff
changeset
|
13 'mimetype': 'text/plain', |
b46b2e5b6c08
Improve error management by separating stdout and stderr
Brendan Rius <brendan@omixy.com>
parents:
0
diff
changeset
|
14 'file_extension': 'c'} |
b46b2e5b6c08
Improve error management by separating stdout and stderr
Brendan Rius <brendan@omixy.com>
parents:
0
diff
changeset
|
15 banner = "C kernel.\n" \ |
b46b2e5b6c08
Improve error management by separating stdout and stderr
Brendan Rius <brendan@omixy.com>
parents:
0
diff
changeset
|
16 "Uses gcc, compiles in C11, and creates source code files and executables in temporary folder.\n" |
b46b2e5b6c08
Improve error management by separating stdout and stderr
Brendan Rius <brendan@omixy.com>
parents:
0
diff
changeset
|
17 |
b46b2e5b6c08
Improve error management by separating stdout and stderr
Brendan Rius <brendan@omixy.com>
parents:
0
diff
changeset
|
18 def __init__(self, *args, **kwargs): |
b46b2e5b6c08
Improve error management by separating stdout and stderr
Brendan Rius <brendan@omixy.com>
parents:
0
diff
changeset
|
19 super(CKernel, self).__init__(*args, **kwargs) |
b46b2e5b6c08
Improve error management by separating stdout and stderr
Brendan Rius <brendan@omixy.com>
parents:
0
diff
changeset
|
20 self.files = [] |
b46b2e5b6c08
Improve error management by separating stdout and stderr
Brendan Rius <brendan@omixy.com>
parents:
0
diff
changeset
|
21 |
b46b2e5b6c08
Improve error management by separating stdout and stderr
Brendan Rius <brendan@omixy.com>
parents:
0
diff
changeset
|
22 def cleanup_files(self): |
b46b2e5b6c08
Improve error management by separating stdout and stderr
Brendan Rius <brendan@omixy.com>
parents:
0
diff
changeset
|
23 """Remove all the temporary files created by the kernel""" |
b46b2e5b6c08
Improve error management by separating stdout and stderr
Brendan Rius <brendan@omixy.com>
parents:
0
diff
changeset
|
24 for file in self.files: |
b46b2e5b6c08
Improve error management by separating stdout and stderr
Brendan Rius <brendan@omixy.com>
parents:
0
diff
changeset
|
25 os.remove(file) |
0 | 26 |
2
b46b2e5b6c08
Improve error management by separating stdout and stderr
Brendan Rius <brendan@omixy.com>
parents:
0
diff
changeset
|
27 def new_temp_file(self, **kwargs): |
b46b2e5b6c08
Improve error management by separating stdout and stderr
Brendan Rius <brendan@omixy.com>
parents:
0
diff
changeset
|
28 """Create a new temp file to be deleted when the kernel shuts down""" |
b46b2e5b6c08
Improve error management by separating stdout and stderr
Brendan Rius <brendan@omixy.com>
parents:
0
diff
changeset
|
29 # We don't want the file to be deleted when closed, but only when the kernel stops |
b46b2e5b6c08
Improve error management by separating stdout and stderr
Brendan Rius <brendan@omixy.com>
parents:
0
diff
changeset
|
30 kwargs['delete'] = False |
b46b2e5b6c08
Improve error management by separating stdout and stderr
Brendan Rius <brendan@omixy.com>
parents:
0
diff
changeset
|
31 file = tempfile.NamedTemporaryFile(**kwargs) |
b46b2e5b6c08
Improve error management by separating stdout and stderr
Brendan Rius <brendan@omixy.com>
parents:
0
diff
changeset
|
32 self.files.append(file.name) |
b46b2e5b6c08
Improve error management by separating stdout and stderr
Brendan Rius <brendan@omixy.com>
parents:
0
diff
changeset
|
33 return file |
b46b2e5b6c08
Improve error management by separating stdout and stderr
Brendan Rius <brendan@omixy.com>
parents:
0
diff
changeset
|
34 |
b46b2e5b6c08
Improve error management by separating stdout and stderr
Brendan Rius <brendan@omixy.com>
parents:
0
diff
changeset
|
35 @staticmethod |
b46b2e5b6c08
Improve error management by separating stdout and stderr
Brendan Rius <brendan@omixy.com>
parents:
0
diff
changeset
|
36 def execute_command(cmd): |
b46b2e5b6c08
Improve error management by separating stdout and stderr
Brendan Rius <brendan@omixy.com>
parents:
0
diff
changeset
|
37 """Execute a command and returns the return code, stdout and stderr""" |
b46b2e5b6c08
Improve error management by separating stdout and stderr
Brendan Rius <brendan@omixy.com>
parents:
0
diff
changeset
|
38 p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
b46b2e5b6c08
Improve error management by separating stdout and stderr
Brendan Rius <brendan@omixy.com>
parents:
0
diff
changeset
|
39 stdout, stderr = p.communicate() |
b46b2e5b6c08
Improve error management by separating stdout and stderr
Brendan Rius <brendan@omixy.com>
parents:
0
diff
changeset
|
40 return p.returncode, stdout, stderr |
b46b2e5b6c08
Improve error management by separating stdout and stderr
Brendan Rius <brendan@omixy.com>
parents:
0
diff
changeset
|
41 |
b46b2e5b6c08
Improve error management by separating stdout and stderr
Brendan Rius <brendan@omixy.com>
parents:
0
diff
changeset
|
42 @staticmethod |
b46b2e5b6c08
Improve error management by separating stdout and stderr
Brendan Rius <brendan@omixy.com>
parents:
0
diff
changeset
|
43 def compile_with_gcc(source_filename, binary_filename): |
b46b2e5b6c08
Improve error management by separating stdout and stderr
Brendan Rius <brendan@omixy.com>
parents:
0
diff
changeset
|
44 args = ['gcc', source_filename, '-std=c11', '-o', binary_filename] |
b46b2e5b6c08
Improve error management by separating stdout and stderr
Brendan Rius <brendan@omixy.com>
parents:
0
diff
changeset
|
45 return CKernel.execute_command(args) |
0 | 46 |
47 def do_execute(self, code, silent, store_history=True, | |
48 user_expressions=None, allow_stdin=False): | |
2
b46b2e5b6c08
Improve error management by separating stdout and stderr
Brendan Rius <brendan@omixy.com>
parents:
0
diff
changeset
|
49 |
b46b2e5b6c08
Improve error management by separating stdout and stderr
Brendan Rius <brendan@omixy.com>
parents:
0
diff
changeset
|
50 retcode, stdout, stderr = None, '', '' |
b46b2e5b6c08
Improve error management by separating stdout and stderr
Brendan Rius <brendan@omixy.com>
parents:
0
diff
changeset
|
51 with self.new_temp_file(suffix='.c') as source_file: |
b46b2e5b6c08
Improve error management by separating stdout and stderr
Brendan Rius <brendan@omixy.com>
parents:
0
diff
changeset
|
52 source_file.write(code) |
b46b2e5b6c08
Improve error management by separating stdout and stderr
Brendan Rius <brendan@omixy.com>
parents:
0
diff
changeset
|
53 source_file.flush() |
b46b2e5b6c08
Improve error management by separating stdout and stderr
Brendan Rius <brendan@omixy.com>
parents:
0
diff
changeset
|
54 with self.new_temp_file(suffix='.out') as binary_file: |
b46b2e5b6c08
Improve error management by separating stdout and stderr
Brendan Rius <brendan@omixy.com>
parents:
0
diff
changeset
|
55 retcode, stdout, stderr = self.compile_with_gcc(source_file.name, binary_file.name) |
3
8ddfdd2a8574
Add retcode to stderr to make errors such as segfaults visible
Brendan Rius <brendan@omixy.com>
parents:
2
diff
changeset
|
56 if retcode != 0: |
4
5c4b5066fab0
Do not try to execute the executable if compilation failed
Brendan Rius <brendan@omixy.com>
parents:
3
diff
changeset
|
57 stderr += "[C kernel] GCC exited with code {}, the executable will not be executed".format(retcode) |
5c4b5066fab0
Do not try to execute the executable if compilation failed
Brendan Rius <brendan@omixy.com>
parents:
3
diff
changeset
|
58 self.log.info("GCC return code: {}".format(retcode)) |
5c4b5066fab0
Do not try to execute the executable if compilation failed
Brendan Rius <brendan@omixy.com>
parents:
3
diff
changeset
|
59 self.log.info("GCC stdout: {}".format(stdout)) |
5c4b5066fab0
Do not try to execute the executable if compilation failed
Brendan Rius <brendan@omixy.com>
parents:
3
diff
changeset
|
60 self.log.info("GCC stderr: {}".format(stderr)) |
0 | 61 |
4
5c4b5066fab0
Do not try to execute the executable if compilation failed
Brendan Rius <brendan@omixy.com>
parents:
3
diff
changeset
|
62 if retcode == 0: # If the compilation succeeded |
5c4b5066fab0
Do not try to execute the executable if compilation failed
Brendan Rius <brendan@omixy.com>
parents:
3
diff
changeset
|
63 retcode, out, err = CKernel.execute_command([binary_file.name]) |
5c4b5066fab0
Do not try to execute the executable if compilation failed
Brendan Rius <brendan@omixy.com>
parents:
3
diff
changeset
|
64 if retcode != 0: |
5c4b5066fab0
Do not try to execute the executable if compilation failed
Brendan Rius <brendan@omixy.com>
parents:
3
diff
changeset
|
65 stderr += "[C kernel] Executable exited with code {}".format(retcode) |
5c4b5066fab0
Do not try to execute the executable if compilation failed
Brendan Rius <brendan@omixy.com>
parents:
3
diff
changeset
|
66 self.log.info("Executable retcode: {}".format(retcode)) |
5c4b5066fab0
Do not try to execute the executable if compilation failed
Brendan Rius <brendan@omixy.com>
parents:
3
diff
changeset
|
67 self.log.info("Executable stdout: {}".format(out)) |
5c4b5066fab0
Do not try to execute the executable if compilation failed
Brendan Rius <brendan@omixy.com>
parents:
3
diff
changeset
|
68 self.log.info("Executable stderr: {}".format(err)) |
5c4b5066fab0
Do not try to execute the executable if compilation failed
Brendan Rius <brendan@omixy.com>
parents:
3
diff
changeset
|
69 stdout += out |
5c4b5066fab0
Do not try to execute the executable if compilation failed
Brendan Rius <brendan@omixy.com>
parents:
3
diff
changeset
|
70 stderr += err |
5c4b5066fab0
Do not try to execute the executable if compilation failed
Brendan Rius <brendan@omixy.com>
parents:
3
diff
changeset
|
71 else: |
5c4b5066fab0
Do not try to execute the executable if compilation failed
Brendan Rius <brendan@omixy.com>
parents:
3
diff
changeset
|
72 self.log.info('Compilation failed, the program will not be executed') |
0 | 73 |
74 if not silent: | |
2
b46b2e5b6c08
Improve error management by separating stdout and stderr
Brendan Rius <brendan@omixy.com>
parents:
0
diff
changeset
|
75 stream_content = {'name': 'stderr', 'text': stderr} |
0 | 76 self.send_response(self.iopub_socket, 'stream', stream_content) |
2
b46b2e5b6c08
Improve error management by separating stdout and stderr
Brendan Rius <brendan@omixy.com>
parents:
0
diff
changeset
|
77 stream_content = {'name': 'stdout', 'text': stdout} |
b46b2e5b6c08
Improve error management by separating stdout and stderr
Brendan Rius <brendan@omixy.com>
parents:
0
diff
changeset
|
78 self.send_response(self.iopub_socket, 'stream', stream_content) |
b46b2e5b6c08
Improve error management by separating stdout and stderr
Brendan Rius <brendan@omixy.com>
parents:
0
diff
changeset
|
79 return {'status': 'ok', 'execution_count': self.execution_count, 'payload': [], 'user_expressions': {}} |