Skip to content

Commit 0adf306

Browse files
committed
fix Windows
1 parent 00638b0 commit 0adf306

File tree

1 file changed

+26
-4
lines changed

1 file changed

+26
-4
lines changed

src/library/module.cpp

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -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
196197
struct 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

Comments
 (0)