@@ -33,6 +33,7 @@ Authors: Leonardo de Moura, Gabriel Ebner, Sebastian Ullrich
3333#ifdef LEAN_WINDOWS
3434#include < windows.h>
3535#include < io.h>
36+ #include < fcntl.h>
3637#else
3738#include < sys/mman.h>
3839#include < unistd.h>
@@ -196,6 +197,9 @@ extern "C" LEAN_EXPORT object * lean_save_module_data_parts(b_obj_arg mod, b_obj
196197struct module_file {
197198 std::string m_fname;
198199 file_descriptor m_fd;
200+ #ifdef LEAN_WINDOWS
201+ HANDLE m_handle; // store the original Windows for mmap
202+ #endif
199203 char * m_base_addr;
200204 size_t m_size;
201205 char * m_buffer;
@@ -210,10 +214,25 @@ extern "C" LEAN_EXPORT object * lean_read_module_data_parts(b_obj_arg ofnames, o
210214 for (auto const & fname : fnames) {
211215 std::string olean_fn = fname.to_std_string ();
212216 try {
217+ #ifdef LEAN_WINDOWS
218+ // Use CreateFile with proper sharing flags, then convert to POSIX fd for shared code
219+ // `FILE_SHARE_DELETE` is necessary to allow the file to (be marked to) be deleted while in use
220+ HANDLE h_file = CreateFile (olean_fn.c_str (), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_DELETE, NULL , OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
221+ if (h_file == INVALID_HANDLE_VALUE) {
222+ return io_result_mk_error ((sstream () << " failed to open file '" << olean_fn << " ': " << GetLastError ()).str ());
223+ }
224+ int raw_fd = _open_osfhandle ((intptr_t )h_file, _O_RDONLY);
225+ if (raw_fd == -1 ) {
226+ CloseHandle (h_file);
227+ return io_result_mk_error ((sstream () << " failed to convert handle to fd for '" << olean_fn << " '" ).str ());
228+ }
229+ file_descriptor fd (raw_fd);
230+ #else
213231 file_descriptor fd (open (olean_fn.c_str (), O_RDONLY));
214232 if (!fd) {
215233 return io_result_mk_error ((sstream () << " failed to open file '" << olean_fn << " ': " << strerror (errno)).str ());
216234 }
235+ #endif
217236
218237 /* Get file size */
219238 struct stat st;
@@ -237,7 +256,11 @@ extern "C" LEAN_EXPORT object * lean_read_module_data_parts(b_obj_arg ofnames, o
237256 return io_result_mk_error ((sstream () << " failed to read file '" << olean_fn << " ', incompatible header" ).str ());
238257 }
239258 char * base_addr = reinterpret_cast <char *>(header.base_addr );
259+ #ifdef LEAN_WINDOWS
260+ files.push_back ({olean_fn, std::move (fd), h_file, base_addr, size, nullptr , nullptr });
261+ #else
240262 files.push_back ({olean_fn, std::move (fd), base_addr, size, nullptr , nullptr });
263+ #endif
241264 } catch (exception & ex) {
242265 return io_result_mk_error ((sstream () << " failed to read '" << olean_fn << " ': " << ex.what ()).str ());
243266 }
@@ -253,16 +276,15 @@ extern "C" LEAN_EXPORT object * lean_read_module_data_parts(b_obj_arg ofnames, o
253276 char * base_addr = file.m_base_addr ;
254277 try {
255278#ifdef LEAN_WINDOWS
256- HANDLE h_olean_fn = (HANDLE)_get_osfhandle (file.m_fd .get ());
257- if (h_olean_fn == INVALID_HANDLE_VALUE) {
258- return io_result_mk_error ((sstream () << " failed to get Windows handle for '" << olean_fn << " ': " << GetLastError ()).str ());
259- }
279+ // Use the stored handle that was created with proper sharing flags
280+ HANDLE h_olean_fn = file.m_handle ;
260281 HANDLE h_map = CreateFileMapping (h_olean_fn, NULL , PAGE_READONLY, 0 , 0 , NULL );
261282 if (h_map == NULL ) {
262283 return io_result_mk_error ((sstream () << " failed to map '" << olean_fn << " ': " << GetLastError ()).str ());
263284 }
264285 char * buffer = static_cast <char *>(MapViewOfFileEx (h_map, FILE_MAP_READ, 0 , 0 , 0 , base_addr));
265286 lean_always_assert (CloseHandle (h_map));
287+ // NOTE: no need to close `h_olean_fn` as it's owned by `file.m_fd`
266288 if (!buffer) {
267289 is_mmap = false ;
268290 break ;
0 commit comments