The following Elisp code adds a function
org+-kill-orphaned-edit-buffers to the special hook
kill-buffer-query-functions buffer-locally in Org buffers.
That function scans the Org buffer for overlays with
edit-buffer property and looks whether that buffer is a live
org-src-edit buffer. If that is the case it tries to kill the source edit buffer.
The true/false-value of the option
org+-query-before-kill-edit-buffer determines whether you should be asked for confirmation if a modified source buffer is going to be killed.
If some modified source buffer is not killed then the original Org buffer is also not killed.
org+-query-before-kill-edit-buffer is nil (the default case) source edit buffers are killed unconditionally. So you only need to confirm killing if the Org buffer itself is modified.
(defcustom org+-query-before-kill-edit-buffer nil
"Query when killing an edited org src buffer."
(defun org+-kill-orphaned-edit-buffers (&optional b e)
"Close orphaned source edit buffers in the region from B to E.
B defaults to `point-min' and E defaults to `point-max'.
In interactive calls B and E are the boundaries of the region
if it is active."
(interactive (when (region-active-p)
(unless b (setq b (point-min)))
(unless e (setq e (point-max)))
(cl-loop with buf
for ol being the overlays from b to e
if (and (setq buf (overlay-get ol 'edit-buffer))
unless (with-current-buffer buf
(or (null org+-query-before-kill-edit-buffer)
(y-or-n-p (format "Buffer %s modified; kill anyway? " (buffer-name)))))
finally return t))
(defun org+-kill-edit-buffers-at-kill-buffer ()
"Close source edit buffer when the current Org buffer is killed."
(add-hook 'kill-buffer-query-functions #'org+-kill-orphaned-edit-buffers t t))
(add-hook 'org-mode-hook #'org+-kill-edit-buffers-at-kill-buffer)