annotate c_kernel/kernel.py @ 7:aa54c85303b6

Remove temporary files when shutting down the kernel
author Brendan Rius <brendan@omixy.com>
date Fri, 25 Mar 2016 14:52:13 +0000
parents 5c4b5066fab0
children 101e99452042
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
50ea00cf5896 Initial commit
Brendan Rius <brendan@omixy.com>
parents:
diff changeset
1 from ipykernel.kernelbase import Kernel
50ea00cf5896 Initial commit
Brendan Rius <brendan@omixy.com>
parents:
diff changeset
2 import subprocess
50ea00cf5896 Initial commit
Brendan Rius <brendan@omixy.com>
parents:
diff changeset
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
50ea00cf5896 Initial commit
Brendan Rius <brendan@omixy.com>
parents:
diff changeset
5
50ea00cf5896 Initial commit
Brendan Rius <brendan@omixy.com>
parents:
diff changeset
6
50ea00cf5896 Initial commit
Brendan Rius <brendan@omixy.com>
parents:
diff changeset
7 class CKernel(Kernel):
50ea00cf5896 Initial commit
Brendan Rius <brendan@omixy.com>
parents:
diff changeset
8 implementation = 'c_kernel'
50ea00cf5896 Initial commit
Brendan Rius <brendan@omixy.com>
parents:
diff changeset
9 implementation_version = '1.0'
50ea00cf5896 Initial commit
Brendan Rius <brendan@omixy.com>
parents:
diff changeset
10 language = 'c'
50ea00cf5896 Initial commit
Brendan Rius <brendan@omixy.com>
parents:
diff changeset
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
50ea00cf5896 Initial commit
Brendan Rius <brendan@omixy.com>
parents:
diff changeset
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
50ea00cf5896 Initial commit
Brendan Rius <brendan@omixy.com>
parents:
diff changeset
46
50ea00cf5896 Initial commit
Brendan Rius <brendan@omixy.com>
parents:
diff changeset
47 def do_execute(self, code, silent, store_history=True,
50ea00cf5896 Initial commit
Brendan Rius <brendan@omixy.com>
parents:
diff changeset
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
50ea00cf5896 Initial commit
Brendan Rius <brendan@omixy.com>
parents:
diff changeset
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
50ea00cf5896 Initial commit
Brendan Rius <brendan@omixy.com>
parents:
diff changeset
73
50ea00cf5896 Initial commit
Brendan Rius <brendan@omixy.com>
parents:
diff changeset
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
50ea00cf5896 Initial commit
Brendan Rius <brendan@omixy.com>
parents:
diff changeset
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': {}}
7
aa54c85303b6 Remove temporary files when shutting down the kernel
Brendan Rius <brendan@omixy.com>
parents: 4
diff changeset
80
aa54c85303b6 Remove temporary files when shutting down the kernel
Brendan Rius <brendan@omixy.com>
parents: 4
diff changeset
81 def do_shutdown(self, restart):
aa54c85303b6 Remove temporary files when shutting down the kernel
Brendan Rius <brendan@omixy.com>
parents: 4
diff changeset
82 """Cleanup the created source code files and executables when shutting down the kernel"""
aa54c85303b6 Remove temporary files when shutting down the kernel
Brendan Rius <brendan@omixy.com>
parents: 4
diff changeset
83 self.cleanup_files()